Использование объявления не работает в RADStudio 2010

Я получаю новый класс из класса VCL TStream:

// A stream based on a temporary file, deleted when the stream is closed

class TTempFileStream : public TStream
{
...
public:
  using TStream::Seek;

   __int64 __fastcall Seek(const __int64 Offset, TSeekOrigin Origin)
  {
    return 0; // for simplicity!
  }

  ... 
} ;

TStream объявляет следующие два варианта поиска:

virtual int __fastcall Seek(int Offset, System::Word Origin)/* overload */;
virtual __int64 __fastcall Seek(const __int64 Offset, TSeekOrigin Origin)/* overload */;

Но я получаю следующее предупреждение W8022 при компиляции моего класса: -

[BCC32 Warning]_utils.h(166): W8022 
'_fastcall TTempFileStream::Seek(const __int64,TSeekOrigin)' hides virtual function '_fastcall TStream::Seek(int,unsigned short)'

Конечно, объявление Using должно исправить это?

Чтобы вернуть этот вопрос в нужное русло, я знаю, как взаимосвязаны две версии TStream::seek, и я просто пытаюсь получить унаследованный метод Seek(int,int), предоставляемый производным классом. Почему моя декларация using этого не делает?


person Roddy    schedule 18.12.2012    source источник
comment
Извините - слишком рано нажала на пост!   -  person Roddy    schedule 18.12.2012
comment
Проблема в том, что объявление функции отличается только типом возвращаемого значения. Вам нужно опубликовать родительский класс, чтобы мы могли предоставить более подробную информацию.   -  person Thomas Matthews    schedule 18.12.2012
comment
@ThomasMatthews: определение Seek родительского класса находится здесь: docwiki.embarcadero .com/Libraries/XE3/ru/   -  person Roddy    schedule 18.12.2012


Ответы (2)


Родди, твой код очень правильный.

Код работает должным образом (проверено) при добавлении с использованием TStream::Seek; в противном случае, как указано в предупреждении, метод базового класса будет скрыт. (эта часть языка C++, Реми впервые вынужден с вами не согласиться).

Предупреждение является ложным срабатыванием, очень старой и еще не исправленной ОШИБКОЙ. в C++ Builder присутствует как минимум с версии 2006 до XE4.

person Niki    schedule 05.09.2013
comment
Спасибо за ссылку на КК. Я ожидаю, что 64-битный компилятор на основе Clang в XE4 исправит это. - person Roddy; 06.09.2013

Вам вообще не нужен оператор using, так что избавьтесь от него. Вы переопределяете 64-битный метод Seek(). Это все, что вам нужно сделать. Вы получаете 32-битный метод Seek() бесплатно, так как это общедоступный метод TStream, и вы используете наследование public в своем производном классе. Вам не нужно ничего объявлять, чтобы получить или использовать 32-битный метод Seek(). Пока вы не переопределите его, он будет внутренне вызывать ваше 64-битное переопределение Seek() при вызове.

class TTempFileStream : public TStream
{
...
public:
    ...
    virtual __int64 __fastcall Seek(const __int64 Offset, TSeekOrigin Origin)
    {
        return 0; // for simplicity!
    }
    ... 
};

К вашему сведению, если все, что вам нужно, это удалить временный файл при закрытии потока, вам вообще не нужен производный класс. Вместо этого вы можете использовать RTL THandleStream как есть, передав ему HANDLE из функции Win32 API CreateFile(), где вы указываете флаг FILE_FLAG_DELETE_ON_CLOSE для CreateFile().

person Remy Lebeau    schedule 18.12.2012
comment
+1 за предложение THandleStream, но мне действительно нужно исправить предупреждение: объявление Using предназначено для этого, раскрывая подписи базового класса, но предупреждение все еще существует. Насколько я знаю, если предупреждение НЕ исправлено, тогда код, вызывающий Seek(int,int), переходит непосредственно к производному классу, а не через метод базового класса. Для TStream это имеет в основном тот же эффект, но в общем случае это, вероятно, плохая идея. - person Roddy; 18.12.2012
comment
Опять же, оператор using НЕПРАВИЛЬНО использовать в этой ситуации. Вам НЕ это нужно. TSeekOrigin объявлен как перечисление. Вы не можете передать ему int без использования приведения типа. Любой код, который вызывает Seek(int, int), вызовет 32-битный Seek(), который затем вызовет ваш переопределенный 64-битный Seek() внутри. TSeekOrigin был реализован как перечисление специально для того, чтобы вызвать такое поведение, поэтому ранее существовавший код, ожидающий 32-битного Seek(), не сломался, когда был введен 64-битный Seek(). Код, который хочет вызвать 64-битный Seek(), должен правильно использовать TSeekOrigin. - person Remy Lebeau; 18.12.2012
comment
Я думаю, что это неправильно: Посмотрите на следующий код: - TFileStream *ss = new TFileStream()); TStream *s(ss); s->Seek(0,0); ss->Seek(0,0); . Первый seek() компилируется нормально, но второй выдает предупреждение W8006 Initializing TSeekOrigin with int, поэтому a: он НЕ вызывает унаследованную (int, int) версию, и b: приведение типов не требуется...? Во всяком случае, основная причина вопроса заключается в том, как избавиться от предупреждения W8022, а удаление using этого не делает. - person Roddy; 19.12.2012
comment
Хорошо, здесь есть что-то особенное. Из еще нескольких (не TSTream) тестов я думаю, что объявление using работает так, как я ожидаю, НО предупреждающее сообщение выводится независимо, что просто странно. - person Roddy; 19.12.2012
comment
Seek(int, int) перегрузки нет. Есть только Seek(int, unsigned short) и Seek(const __int64, TSeekOrigin). Seek(0, 0) соответствует первому, а не второму. Я смог воспроизвести проблему в XE2. Я думаю, что это ошибка компилятора. Оператор using не нужен. Его нет в стандартных классах VCL TStream, и они прекрасно работают, не выдавая никаких предупреждений/ошибок. Ваш переопределенный Seek() является правильным переопределением, он ничего не скрывает. Компилятор ошибается. - person Remy Lebeau; 19.12.2012