Сейчас на форуме: vsv1 (+5 невидимых)

 eXeL@B —› Вопросы новичков —› Ссылка не указывает на невертуальный метод
Посл.ответ Сообщение

Ранг: 4.2 (гость)
Активность: 0.020
Статус: Участник

Создано: 26 февраля 2016 00:19 · Поправил: bolvai
· Личное сообщение · #1

Столкнулся с тем что ссылка в классе не указывает на реализующий метод, а указывает на виртуальный(Т.е пустой).
Все дело в том что реализация этого метода задана специфично, по средствам наследования класса(А не в CPP), т.е в классе Archive задается virtual void Read{}; А далее задается ArchiveReader : public Archive и в нем уже реализуется виртуальный void Read{со всей логикой};
и я не пойму ввиду чего но ссылка на этот самый ArchiveReader не идет.
Объявлено все следующим образом

Code:
  1. main.cpp
  2.  
  3. Archive& operator<<(Archive& Ar, INT& I)
  4. {
  5.  
  6.          Ar.ByteRead(&I, sizeof(I));
  7.          return Ar;
  8. }


Code:
  1. class Archive
  2. {
  3. public:
  4.         virtual void Read( void* V, INT Length )
  5.          {}
  6.          Archive& ByteRead( void* V, INT Length )
  7.          {
  8.                  Read(V, Length);
  9.         }
  10. }


Code:
  1. class ArchiveReader : public Archive
  2. {
  3. public:
  4.    void Read( void* V, INT Length )
  5.     {
  6.                  FScopeCriticalSection Lock( &AccessLock );
  7.  
  8.                  void* dest = V;
  9.                  INT prev = Pos;
  10.                  INT length = Length;
  11.  
  12.         while( Length>0 )
  13.         {
  14.                     INT Count=0;
  15.                     ReadFile( Handle, V, Length, (DWORD*)&Count, NULL );
  16.         
  17.                     Pos += Length;
  18.                     BufferBase += Length;
  19.                 
  20.              
  21.                    Copy = Min( Length, BufferBase+BufferCount-Pos );
  22.             
  23.                    appMemcpy( V, Buffer+Pos-BufferBase, Copy );
  24.                    Pos       += Copy;
  25.                    Length    -= Copy;
  26.                    V          = (BYTE*)V+Copy;
  27.         }
  28.  
  29.     }
  30. }


Собственно я пробовал сделать переопределение внутри Archive, чтобы указать сразу на ArchiveReader , но что то у меня с этим постоянно затруднения возникают.
Code:
  1. ArchiveReader* Arr = (ArchiveReader*);

Помогите плиз




Ранг: 105.6 (ветеран), 36thx
Активность: 0.10
Статус: Участник

Создано: 26 февраля 2016 02:23
· Личное сообщение · #2

bolvai пишет:
class Archive

bolvai пишет:

class ArchiveReader : public FArchive

у тебя классы разные как бы. Или покажи полную цепочку наследования.
И в конструкторе/деструкторе виртуальные функции использовать не стоит ( на всякий пожарный ).



Ранг: 4.2 (гость)
Активность: 0.020
Статус: Участник

Создано: 26 февраля 2016 12:59
· Личное сообщение · #3

Dart Sergius пишет:
у тебя классы разные как бы. Или покажи полную цепочку наследования.

Да нет они теже просто немного ошибся !
Я пользуюсь тем что есть, это не мой код, но он работает только в VS 2005, я пытаюсь его обрезать и приспособить для VS 2013 но не очень успешно как видно.

Что еще мне скинуть ?




Ранг: 105.6 (ветеран), 36thx
Активность: 0.10
Статус: Участник

Создано: 26 февраля 2016 15:54
· Личное сообщение · #4

bolvai в последнем большом куске кода обрати внимание на то что метод Read у тебя НЕ виртуальный. Соответсвенно когда базовые методы вызывают ВИРТАУЛЬНЫЙ метод - то они НЕ вызовут твою обычную перегруженную функцию. Укажите virtual.
Ну хорошо бы конечно хотя бы хедеры показать полностью и часть cpp - где собственно и как вызываете и что показывает в отладчике...



Ранг: 33.4 (посетитель), 24thx
Активность: 0.020
Статус: Участник

Создано: 26 февраля 2016 15:55 · Поправил: redlord
· Личное сообщение · #5

Code:
  1. class Archive
  2. {
  3. public:
  4.          virtual void Read( void* V, int Length )
  5.          {}
  6.          Archive& ByteRead( void* V, int Length )
  7.          {
  8.                  Read(V, Length);
  9.                  return *this;
  10.          }
  11. };
  12.  
  13.  
  14. class ArchiveReader : public Archive
  15. {
  16.          void Read( void* V, int Length )
  17.          {
  18.                  printf("ok\n");
  19.          }
  20. };
  21.  
  22. Archive& operator<<(Archive& Ar, int& I)
  23. {
  24.  
  25.          Ar.ByteRead(&I, sizeof(I));
  26.          return Ar;
  27. }
  28.  
  29. int main()
  30. {
  31.          
  32.          ArchiveReader d;
  33.          int x = int();
  34.          d << x;
  35. }
  36.  


код должен напечатать ok в консоли



Ранг: 4.2 (гость)
Активность: 0.020
Статус: Участник

Создано: 26 февраля 2016 16:51 · Поправил: bolvai
· Личное сообщение · #6

Dart Sergius пишет:
Ну хорошо бы конечно хотя бы хедеры показать полностью и часть cpp - где собственно и как вызываете и что показывает в отладчике...

Я привел часть из CPP - оператор как раз там реализован
Code:
  1. Archive& operator<<(Archive& Ar, int& I)
  2. {
  3.  
  4.          Ar.ByteRead(&I, sizeof(I));
  5.          return Ar;
  6. }

Code:
  1.          
  2. Archive* Ar;
  3. *Ar << Summary;
  4. printf("Summary Tag:%x", Summary.Tag);

Summary.Tag это INT значение, по сему идет переключение в Archive& operator<<(Archive& Ar, int& I), а оттуда уже оно светит в Ar.ByteRead, где собственно в дебаге показывает что оно указывает на void read Arhive Virtual, вместо void ArchiveReader, причем в дебаге от 2005 с оригиналом там все показывает нормально.
redlord пишет:
int main()
{
         
         ArchiveReader d;
         int x = int();
         d << x;
}
 

Тут как раз с переопределением и вся проблема - при таком написании - выдает ошибку, для класса не существует конструктора по умолчанию.



Ранг: 33.4 (посетитель), 24thx
Активность: 0.020
Статус: Участник

Создано: 26 февраля 2016 16:56 · Поправил: redlord
· Личное сообщение · #7

bolvai

если добавить конструктор?

class ArchiveReader : public Archive
{
ArchiveReader():Archive(){}
};

P.S.
Archive* Ar; /// что это? указатель на что?
можно увидеть весь main?



Ранг: 4.2 (гость)
Активность: 0.020
Статус: Участник

Создано: 26 февраля 2016 17:32 · Поправил: bolvai
· Личное сообщение · #8

redlord пишет:
Archive* Ar; /// что это? указатель на что?

Да указатель на другой метод CreateFileReader, с ним особых накладок нету, да и в принципе не в нем дело.
Я мог и объявить просто Archive Ar;

ReadFile(Infile,&Ar,size,0);

Ar << x;

И ссылка в операторе
Ar.ByteRead(&I, sizeof(I));
всеравно бы указывала на пустой виртуальный метод вместо того что в ArchiveReader;

Наверное это какие то особенности настроек того проекта от Vs 2005, которые я не очень замечаю =( .

Вот собственно еще кода из ArchiveReader забыл добавить конструктор
Code:
  1.     ArchiveReader( HANDLE InHandle, FOutputDevice* InError, INT InSize )
  2.     :   Handle          ( InHandle )
  3.     ,   Error           ( InError )
  4.     ,   Size            ( InSize )
  5.     ,   Pos             ( 0 )
  6.     ,   BufferBase      ( 0 )
  7.     ,   BufferCount     ( 0 )
  8.     {
  9.         ArIsLoading = ArIsPersistent = 1;
  10.     }

Тут проблема в том что есть переменные в стеке Handle Error size, Которые создаются вот тут
Code:
  1. class FFileManagerWindows : public FFileManagerGeneric
  2. {
  3. public:
  4.     Archive* CreateFileReader( const TCHAR* Filename, DWORD Flags, FOutputDevice* Error )
  5.     {
  6.         guard(FFileManagerWindows::CreateFileReader);
  7.         DWORD  Access    = GENERIC_READ;
  8.         DWORD  WinFlags  = FILE_SHARE_READ;
  9.         DWORD  Create    = OPEN_EXISTING;
  10.         HANDLE Handle    = TCHAR_CALL_OS( CreateFileW( Filename, Access, WinFlags, NULL, Create, FILE_ATTRIBUTE_NORMAL, NULL ), CreateFileA( TCHAR_TO_ANSI(Filename), Access, WinFlags, NULL, Create, FILE_ATTRIBUTE_NORMAL, NULL ) );
  11.         if( Handle==INVALID_HANDLE_VALUE )
  12.         {
  13.             if( Flags & FILEREAD_NoFail )
  14.                 appErrorf( TEXT("Failed to read file: %s"), Filename );
  15.             return NULL;
  16.         }
  17.         return new(TEXT("WindowsFileReader"))ArchiveReader(Handle,Error,GetFileSize(Handle,NULL));
  18.         unguard;
  19.     }
  20. }

И по сути правильное обращение из Main выглядит так
Code:
  1. Archive* Ar = FileManager->CreateFileReader(L"File.txt", 0, GError);
Но проблема так же остается падает внутри

ибо то что идет в INT Оператор
Code:
  1. Archive& operator<<(Archive& Ar, INT& I)
  2. {
  3.          ArchiveReader arr(NULL, NULL, NULL);
  4.          arr.read(&I, sizeof(I));
  5. //       Ar.ByteRead(&I, sizeof(I));
  6.          return reader;
  7. }

Не допускает дописания Handle error и size, а получить их неоткуда.

Не пойму как оно в оригинале все переопределялось правильно ?




Ранг: 105.6 (ветеран), 36thx
Активность: 0.10
Статус: Участник

Создано: 26 февраля 2016 17:41
· Личное сообщение · #9

bolvai операторы не могут быть виртуальными если что.
bolvai пишет:
а получить их неоткуда.

что вам мешает их взять из FArchive& Ar ?

Ваще какая-то каша здесь происходит.
В начале у вас была проблема с вызовом виртуальной функции ( вызывалось не та ).
Сейчас вы оператором бинарного сдвига читаете какую-то структуру ( на которую наверняка не написан оператор ).
Теперь вы в операторе бинарного сдвига создаете объект ( хотя вам передают в параметрах объект ), что-то с него пытаетесь прочитать и возвращаете глобальную переменную?????
Что за наркомания, простите пожалуйста ?



Ранг: 4.2 (гость)
Активность: 0.020
Статус: Участник

Создано: 26 февраля 2016 17:47
· Личное сообщение · #10

Dart Sergius пишет:
Ваще какая-то каша здесь происходит.
В начале у вас была проблема с вызовом виртуальной функции ( вызывалось не та ).
Сейчас вы оператором бинарного сдвига читаете какую-то структуру ( на которую наверняка не написан оператор ).
Теперь вы в операторе бинарного сдвига создаете объект ( хотя вам передают в параметрах объект ), что-то с него пытаетесь прочитать и возвращаете глобальную переменную?????

Это я так решить пытался, дело та тут в том что
Ar.ByteRead(&I, sizeof(I));
как раз и есть та проблема с вызовом виртуальной функции - вместо той что в ARchiveReader, т.е этого почему то не происходит, я пытался представить ArchiveReader, но да это глупость.
из Оператора Archive << оно попадает суда

Code:
  1.   Archive& ByteRead( void* V, INT Length )
  2.          {
  3.                  Read(V, Length);
  4.         }

а Read Должно быть не виртуальным от Archive а с фуникцоналом от ArchiveReader, но опять же этого не происходит.




Ранг: 105.6 (ветеран), 36thx
Активность: 0.10
Статус: Участник

Создано: 26 февраля 2016 17:53
· Личное сообщение · #11

bolvai тогда кастуй.
Code:
  1. static_cast<ArchiveReader*>(this)->Read(v,Length)

Вы обозвали в базовом классе виртуальную функцию, и удивляетесь почему в базовом классе не вызвается НЕВИРТУАЛЬНАЯ функция наследника ? Откуда базовый класс будет знать о ней? Почему не сделаете нормальную виртуальную функцию в наследнике - в которой вызовите все что угодно?



Ранг: 4.2 (гость)
Активность: 0.020
Статус: Участник

Создано: 26 февраля 2016 18:00
· Личное сообщение · #12

Dart Sergius пишет:
Вы обозвали в базовом классе виртуальную функцию, и удивляетесь почему в базовом классе не вызвается НЕВИРТУАЛЬНАЯ функция наследника ? Откуда базовый класс будет знать о ней? Почему не сделаете нормальную виртуальную функцию в наследнике - в которой вызовите все что угодно?

Я ориентируюсь по тому коду что в оригинале ) особо не из чего было выбирать, там видно какие то особые настройки странно как то.
сейчас попробую с кастом.



Ранг: 33.4 (посетитель), 24thx
Активность: 0.020
Статус: Участник

Создано: 26 февраля 2016 18:24 · Поправил: redlord
· Личное сообщение · #13

Dart Sergius пишет:
не вызвается НЕВИРТУАЛЬНАЯ функция наследника


отсутствие virtual у функции в классе наследнике не делает ее невиртуальной


bolvai
код ниже работает как и ожидалось.
VS2008, EDG 4.10
можно создать проект новый и компильнуть код

Code:
  1.  
  2.  
  3. #include <stdio.h>
  4.  
  5. class Archive
  6. {
  7. public:
  8.          virtual void Read( void* V, int Length )
  9.          {
  10.          }
  11.          Archive& ByteRead( void* V, int Length )
  12.          {
  13.                  Read(V, Length);
  14.                  return *this;
  15.          }
  16. };
  17.  
  18.  
  19. class ArchiveReader : public Archive
  20. {
  21.          void Read( void* V, int Length )
  22.          {
  23.                  printf("ok\n");
  24.          }
  25. };
  26.  
  27. Archive& operator<<(Archive& Ar, int& I)
  28. {
  29.  
  30.          Ar.ByteRead(&I, sizeof(I));
  31.          return Ar;
  32. }
  33.  
  34. Archive* CreateFileReader()
  35. {
  36.          return new ArchiveReader();
  37. }
  38.  
  39. int main()
  40. {
  41.          
  42.          Archive* d = CreateFileReader();
  43.          int x = int();
  44.          *<< x;
  45. }
  46.  
  47.  


bolvai пишет:
Я мог и объявить просто Archive Ar;


вот тогда точно никакой виртуальности не будет.

| Сообщение посчитали полезным: bolvai

Ранг: 4.2 (гость)
Активность: 0.020
Статус: Участник

Создано: 26 февраля 2016 21:41 · Поправил: bolvai
· Личное сообщение · #14

redlord пишет:
код ниже работает как и ожидалось.
VS2008, EDG 4.10
можно создать проект новый и компильнуть код

Спасибо разобрался!
там был специфичный new оператор, из-за которого все почему то падали, поскольку не было игнора MSTRLIB;
return new(TEXT("WindowsFileReader"))ArchiveFileReader(Handle, Error, GetFileSize(Handle, NULL));
Сделал по проще return new ArchiveFileReader(Handle, Error, GetFileSize(Handle, NULL));
и убрал переопределение операторов и заработало - спасибо!

P.S.
Вот только блин какой то баг там возникает с массивами( тоже кастомные) почему то падает постоянно, при простой инициализации их, стоит опять создать отдельную тему ?



Ранг: 33.4 (посетитель), 24thx
Активность: 0.020
Статус: Участник

Создано: 26 февраля 2016 22:07 · Поправил: redlord
· Личное сообщение · #15

bolvai
тут тематика форума иная.
Думаю, на васме этот вопрос более уместен.
И плюсовиков там хватает
P.s. Поменять оператор new - это хорошо
Только это - костыль
Нужно понять, что он делает и что валит код
Возможно, это поможет понять, что валит массивы



Ранг: 4.2 (гость)
Активность: 0.020
Статус: Участник

Создано: 26 февраля 2016 23:09 · Поправил: bolvai
· Личное сообщение · #16

redlord пишет:
Возможно, это поможет понять, что валит массивы

Возможно конечно что Operator new и валит ибо массивы частично
Code:
  1. new(Sum.Generations)FGenerationInfo(Sum.ExportCount, Sum.NameCount);

именно так и инициализируются, но мне кажется что это не то, поскольку если я просто объявлю даже std::vector просто вот так, вот программа падает, щас конечно возьмусь за дебагер и постараюсь понять, но там что то указывало на alloc, возможно всетаки какое то еще переопределение все ломает.

P.S.
Мне тут хоть реально помогают и чему то новому обучаюсь, чего нельзя сказать о других форумах где я кое что хотел узнать...
тут как то по умнее чтоли.




Ранг: 105.6 (ветеран), 36thx
Активность: 0.10
Статус: Участник

Создано: 26 февраля 2016 23:29
· Личное сообщение · #17

bolvai пишет:
return new(TEXT("WindowsFileReader"))ArchiveFileReader(Handle, Error, GetFileSize(Handle, NULL));

а вы уверены что вам нормальные сырцы дали? Оно как-то работало? Этот new размещает объект ArchiveFileReader на месте строки "WindowsFileReader" !!!



Ранг: 4.2 (гость)
Активность: 0.020
Статус: Участник

Создано: 26 февраля 2016 23:54
· Личное сообщение · #18

Dart Sergius пишет:
а вы уверены что вам нормальные сырцы дали? Оно как-то работало? Этот new размещает объект ArchiveFileReader на месте строки "WindowsFileReader" !!!

Сорцы то те, это я просто видно что то не добавил, либо добавил не правильно, там в оригинале ArchiveFileReader находиться в файле FFileManagerWindows.h, а то откуда он вызывается Core.cpp, не имеет include FFileManagerWindows, оно даже там закоменчено, но темнеменее ссылка имеется! Я проверял все другие include в core.cpp И они не вели к FFilemanagerWindows, пока что мистика это.
Вроде бы моя замена не каких проблем не создает, попробую пока что так.



Ранг: 33.4 (посетитель), 24thx
Активность: 0.020
Статус: Участник

Создано: 27 февраля 2016 00:35 · Поправил: redlord
· Личное сообщение · #19

bolvai
читаните книжек по плюсам
например, джосатис - вандервуд. книжка про шаблоны, но она единственная, где грамотно расписаны тонкости языка. чувствуете разницу межде declaration и definition?
заодно, узнаете, что такое forward declaration и что не всегда нужен инклуд



Ранг: 4.2 (гость)
Активность: 0.020
Статус: Участник

Создано: 27 февраля 2016 01:33
· Личное сообщение · #20

redlord пишет:
например, джосатис - вандервуд. книжка про шаблоны, но она единственная, где грамотно расписаны тонкости языка. чувствуете разницу межде declaration и definition?

Хех Заинтересовали, глянуть бы ),

А на счет этих массивов я разобрался) опять ерундовая помеха - надо было проинициализровать его, а я его этого не знал =), ибо опятьжеж сурс не мой) адаптируюсь.


 eXeL@B —› Вопросы новичков —› Ссылка не указывает на невертуальный метод
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати