Вызов виртуальных методов в конструкторах
Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain
BBB
Противоречие НЕ в том, в какой последовательности вызываются конструкторы. Я писал о том, что таблица виртуальных функций инициализируется в последнем действии конструктора, а не до него.
Противоречие НЕ в том, в какой последовательности вызываются конструкторы. Я писал о том, что таблица виртуальных функций инициализируется в последнем действии конструктора, а не до него.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
#define while if
Оптимизация по размеру:
#define struct union
Совершенно неочевидно. Я согласен, что при входе в тело констркутора vptr уже проинициализирован.Airhand писал(а): Я писал о том, что таблица виртуальных функций инициализируется в последнем действии конструктора, а не до него.
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Airhand, я не отвечал долго потому, что решил набросать программку, которая подтвердит мои слова, а также докажет, что не каждой книге можно доверять. Есть признанные авторы, которых стоит читать, например Страуструп. Автор же упомянутой статьи писал о вещах, в которых толком не разбирается. Airhand, не верь всему, что написано в интернете. Интернет большой, а авторов очень много и не все они глаголят истину. Ты же не веришь всему, что написано на заборе возле твоего дома?
И здесь тоже доверяй, но проверяй.
Короче вот программа:
Вот output программы у меня:

Короче вот программа:
Код: Выделить всё
#include <iostream>
static const void* g_pBaseTableHead = NULL;
static const void* g_pDerivedTableHead = NULL;
const void* GetVPtr(const void* pObject)
{
const long nTableAddr = *((const long*)pObject);
const void* pTableHead = (const void*)nTableAddr;
return pTableHead;
}
const void* PrintObjectInfoAndGetTable(const char* pszClassName, const void* pObject)
{
std::cout << "Information for object of class '" << pszClassName << "'" << std::endl;
std::cout << "Object address: " << pObject << std::endl;
const void* pVPtr = GetVPtr(pObject);
std::cout << "Address of virtual table: " << (const void*)pVPtr << std::endl << std::endl;
return pVPtr;
}
void DumpVTable(const void* pVPtr)
{
std::cout << "Dumping virtual table by double words. Table address: " << pVPtr << std::endl;
const long* pDWordsRepresentation = (const long*)pVPtr;
for (int i = 0; i < 5; i++)
{
std::cout << std::hex << "0x" << pDWordsRepresentation[i] << " ";
}
std::cout << std::endl << std::endl;
}
class CBase
{
public:
CBase()
{
g_pBaseTableHead = PrintObjectInfoAndGetTable("CBase", this);
DumpVTable(g_pBaseTableHead);
}
virtual void V1() = 0;
virtual void V2() = 0;
};
class CDerived : public CBase
{
public:
CDerived()
{
g_pDerivedTableHead = PrintObjectInfoAndGetTable("CDerived", this);
DumpVTable(g_pBaseTableHead);
DumpVTable(g_pDerivedTableHead);
}
virtual void V1() {}
virtual void V2() {}
virtual void V3() {}
};
int main()
{
CDerived derived;
return 0;
}
Код: Выделить всё
Information for object of class 'CBase'
Object address: 0012FF7C
Address of virtual table: 0046F0EC
Dumping virtual table by double words. Table address: 0046F0EC
0x407530 0x407530 0x0 0x7373696d 0x20676e69
Information for object of class 'CDerived'
Object address: 0012FF7C
Address of virtual table: 0046F0D4
Dumping virtual table by double words. Table address: 0046F0EC
0x407530 0x407530 0x0 0x7373696d 0x20676e69
Dumping virtual table by double words. Table address: 0046F0D4
0x4010eb 0x40118b 0x4011bd 0x0 0x73614243
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Естествено у вас будут другие цифры, но нам нужны не сами цифры, а закономерности. Давайте разберём код.
И так, в конструкторе базового и производного класса выводится значение указателя на виртуальные таблицу. Из output'а видно, что указатель имеет корректное значение уже в конструкторе (а не устанавливается после завершения конструктора), а также видно, что значение указателя разное в конструкторе базового и наследника. То есть всё работает согласно схеме, которую я вывел путём умозаключений. Теперь это подтверждено фактами.
Теперь что касается строчек "Dumping virtual table". Дампинг производится три раза. Два раза для таблицы базового класса (из конструктора базового и из конструктора наследника) и один раз для таблицы наследника (из конструктора наследника). Первые два выводы признаны показать, что виртуальные таблицы НЕ МЕНЯЮТСЯ в runtime! Прошу читателей внимательно посмотреть на output, и убедится, что содержимое таблицы базового класса (0046F0EC) идентично в первом и во втором выводе. Таблица наследника выведена для наглядности, а также для того, чтобы я мог немного рассказать вообще о структуре виртуальных таблиц.
Первое, на что хочу обратить внимание - это некий коварный адрес 0x407530, который фигурирует в двух первых ячейках таблицы базового класса (таблица с адресом 0046F0EC). Если посмотреть на код, то мы увидим, что методы, соответствующие этим адресам являются pure virtual. Вначале мы удивимся и скажем: "Так ведь в таком случае в таблице должны быть нули!". Однако это вывод поспешен. Если немного подумать, то мы поймём, что операционная система не может различить когда у нас произошёл pure virtual вызов и если бы там были нули, но наше приложение бы корилось (напомню, что никаких проверок перед вызовом не делается). Таким образом мы осознаём, что этот магический адрес - это не что иное, как адрес функции, которая показывает сообщение об ошибке, а потом завершает выполнение программы. То есть и программист доволен, что он знает где исправлять, и программа не скорилась, а завершила работу корректно. Отсюда мы почерпнули важные знания: об ошибке "pure virtual call" нам сообщает не система, а сама наша программа, благодаря грамотно написанному компилятору.
Сразу после двух ячеек с адресом обработчика ошибки мы видим нулевой адрес. Становится очевидным, что ноль обозначает конец виртуальной таблицы. Всё что идёт за терминирующим нулём - это уже не наша область памяти.
Перейдём к дампингу таблицы класса-наследника (таблица с адресом 0046F0D4). Здесь мы видим, что первые две ячейки таблицы, заполнены уже не адресом обработчика ошибок, а двумя честными адресами методов. Честным адресом метода также является и третья ячейка таблицы (обратите внимание по коду, что класс-наследник имеет дополнительный метод V3). Четвёртая ячейка хранит терминирующий ноль, что мы и ожидали увидеть.
Надеюсь, пример достаточно нагляден, чтобы решить все споры?
И так, в конструкторе базового и производного класса выводится значение указателя на виртуальные таблицу. Из output'а видно, что указатель имеет корректное значение уже в конструкторе (а не устанавливается после завершения конструктора), а также видно, что значение указателя разное в конструкторе базового и наследника. То есть всё работает согласно схеме, которую я вывел путём умозаключений. Теперь это подтверждено фактами.
Теперь что касается строчек "Dumping virtual table". Дампинг производится три раза. Два раза для таблицы базового класса (из конструктора базового и из конструктора наследника) и один раз для таблицы наследника (из конструктора наследника). Первые два выводы признаны показать, что виртуальные таблицы НЕ МЕНЯЮТСЯ в runtime! Прошу читателей внимательно посмотреть на output, и убедится, что содержимое таблицы базового класса (0046F0EC) идентично в первом и во втором выводе. Таблица наследника выведена для наглядности, а также для того, чтобы я мог немного рассказать вообще о структуре виртуальных таблиц.
Первое, на что хочу обратить внимание - это некий коварный адрес 0x407530, который фигурирует в двух первых ячейках таблицы базового класса (таблица с адресом 0046F0EC). Если посмотреть на код, то мы увидим, что методы, соответствующие этим адресам являются pure virtual. Вначале мы удивимся и скажем: "Так ведь в таком случае в таблице должны быть нули!". Однако это вывод поспешен. Если немного подумать, то мы поймём, что операционная система не может различить когда у нас произошёл pure virtual вызов и если бы там были нули, но наше приложение бы корилось (напомню, что никаких проверок перед вызовом не делается). Таким образом мы осознаём, что этот магический адрес - это не что иное, как адрес функции, которая показывает сообщение об ошибке, а потом завершает выполнение программы. То есть и программист доволен, что он знает где исправлять, и программа не скорилась, а завершила работу корректно. Отсюда мы почерпнули важные знания: об ошибке "pure virtual call" нам сообщает не система, а сама наша программа, благодаря грамотно написанному компилятору.
Сразу после двух ячеек с адресом обработчика ошибки мы видим нулевой адрес. Становится очевидным, что ноль обозначает конец виртуальной таблицы. Всё что идёт за терминирующим нулём - это уже не наша область памяти.
Перейдём к дампингу таблицы класса-наследника (таблица с адресом 0046F0D4). Здесь мы видим, что первые две ячейки таблицы, заполнены уже не адресом обработчика ошибок, а двумя честными адресами методов. Честным адресом метода также является и третья ячейка таблицы (обратите внимание по коду, что класс-наследник имеет дополнительный метод V3). Четвёртая ячейка хранит терминирующий ноль, что мы и ожидали увидеть.
Надеюсь, пример достаточно нагляден, чтобы решить все споры?

Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Так покажи мне ссылку на его слова. Я не разбирался в твоей проге и в её выводе.Romeo писал(а):Airhand, я не отвечал долго потому, что решил набросать программку, которая подтвердит мои слова, а также докажет, что не каждой книге можно доверять. Есть признанные авторы, которых стоит читать, например Страуструп.
Тот автор, как я позже узнал, Ален Голуб.Автор же упомянутой статьи писал о вещах, в которых толком не разбирается. Airhand, не верь всему, что написано в интернете. Интернет большой, а авторов очень много и не все они глаголят истину.
Я бы так не говорил про него. То, что ты утверждаеш тоже в инете находится. А проверить некак.Ты же не веришь всему, что написано на заборе возле твоего дома?И здесь тоже доверяй, но проверяй.
--------------------------------------------------------------------------------
Добавлено сообщение
--------------------------------------------------------------------------------
Кто тебе сказал, что то, что ты печатаешь - таблица виртуальных функций. Точно так же это может быть тем, что на заборе написано.Romeo писал(а):И так, в конструкторе базового и производного класса выводится значение указателя на виртуальные таблицу. Из output'а видно, что указатель имеет корректное значение уже в конструкторе (а не устанавливается после завершения конструктора), а также видно значение указателя разное в конструкторе базового и наследника. То есть всё работает согласно схеме, которую я вывел путём умозаключений. Теперь это подтверждено фактами.
Кто тебе сказал, что они меняются во время выполнения. Я утверждал и настаиваю, что иерархия классов сушествует только во время компияции. После уже ничего не меняется. Виртуальные функции - это механизм времени компиляции.Теперь что касается строчек "Dumping virtual table". Дампинг производится три раза. Два раза для таблицы базового класса (из конструктора базового и из конструктора наследника) и один раз для таблицы наследника (из конструктора наследника). Первые два выводы признаны показать, что виртуальные таблицы НЕ МЕНЯЮТСЯ в runtime!
Кто тебе сказал, что это терминирующий ноль ? Это что тебе С-строка ?
Сразу после двух ячеек с адресом обработчика ошибки мы видим нулевой адрес. Становится очевидным, что ноль обозначает конец виртуальной таблицы.
Сам разобрал пример, т.е. истолковал всё и спор закончен ?Надеюсь, пример достаточно нагляден, чтобы решить все споры?![]()
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
#define while if
Оптимизация по размеру:
#define struct union
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
То, что утверждаю я, тоже находится в интернете, но оно, в отличие от той статьи, снабжено доказательствами. Я не знаю кто такой Ален Голуб, более того, в той статье не указано, что статья принадлежит именно этому человеку. Да, собственно, мне не важно кто он: тот, кто пишет подобное как специалист не достоин моего уважения.
Почему у тебя хватило времени на то, что прочитать статью непонятно кого, но не хватило времени просмотреть мою небольшую заметку, снабжённую доказательствами? Или ты читаешь только большие статьи?
Книги Страуструпа смотри в интернете. Кстати, на той самой страничке, которую ты давал нам для ознакомления, снизу куча ссылок, в том числе и на главы из книг Страуструпа (кстати, если не знаешь, то это создатель языка С++). К сожалению я сходу не смог найти там ссылки на главы именно о вызове виртуальных функций в конструкторах, но ты можешь погуглить.
Airhand, зачем ты споришь, не понимая толком о чём идёт речь? По твоим постам я вижу, что у тебя сейчас в голове каша - это видно и по постоянной неточной или ошибочной терминологии и по тому, как твои взгляды резко меняются от одного сообщения к другому. Возможно, эта каша со временем кристаллизуется в академические знания, но пока ты лишь напрасно надрываешься, пытаясь предстать перед всеми знающим человеком и с каждым постом, сам того не подозревая, всё более оголяя свою невежественность.
Почему у тебя хватило времени на то, что прочитать статью непонятно кого, но не хватило времени просмотреть мою небольшую заметку, снабжённую доказательствами? Или ты читаешь только большие статьи?

Книги Страуструпа смотри в интернете. Кстати, на той самой страничке, которую ты давал нам для ознакомления, снизу куча ссылок, в том числе и на главы из книг Страуструпа (кстати, если не знаешь, то это создатель языка С++). К сожалению я сходу не смог найти там ссылки на главы именно о вызове виртуальных функций в конструкторах, но ты можешь погуглить.
Эммм, Airhand, твои слова только подтверждают твою необразованность. То, что все компиляторы Microsoft без исключения и ещё по крайней мере 95 процентов других компиляторов всех марок и мастей размещают указатель на таблицу виртуальных функций в первом машинном слове (для Win32 - это четыре байта) объекта - это общеизвестный факт." писал(а):Кто тебе сказал, что то, что ты печатаешь - таблица виртуальных функций. Точно так же это может быть тем, что на заборе написано.
Именно ты, а также автор указанной тобой статьи, утверждаете, что виртуальные таблицы изменяются во время выполнения. Пример показывает, что это не так." писал(а):Кто тебе сказал, что они меняются во время выполнения. Я утверждал и настаиваю, что иерархия классов сушествует только во время компияции. После уже ничего не меняется.
Виртуальные функции - это, как раз, механизм времени исполнения. Почитай литературу, в частности, что такое "позднее связывание"." писал(а): Виртуальные функции - это механизм времени компиляции.
Посмотрите на этот самолёт. Видите, у него есть руль, как и у моей игрушечной машинки. Вы что, глупы и ничего не понимаете? Никакой это не самолёт - это автомобиль!" писал(а):Кто тебе сказал, что это терминирующий ноль ? Это что тебе С-строка ?
Согласен, я поспешил с выводом, что пример понятен всем. Он понятен только знатокам С++. Собственно, знатокам эта статья и адресовалась." писал(а):Сам разобрал пример, т.е. истолковал всё и спор закончен ?
Airhand, зачем ты споришь, не понимая толком о чём идёт речь? По твоим постам я вижу, что у тебя сейчас в голове каша - это видно и по постоянной неточной или ошибочной терминологии и по тому, как твои взгляды резко меняются от одного сообщения к другому. Возможно, эта каша со временем кристаллизуется в академические знания, но пока ты лишь напрасно надрываешься, пытаясь предстать перед всеми знающим человеком и с каждым постом, сам того не подозревая, всё более оголяя свою невежественность.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ничем оно не снабжено.То, что утверждаю я, тоже находится в интернете, но оно, в отличие от той статьи, снабжено доказательствами.
Это ты называеш себя образованным человеком и не знаеш кто такой Ален Голуб ? Я твою заметку даже разобрал, о чём и выписал кучу замечаний.Почему у тебя хватило времени на то, что прочитать статью непонятно кого, но не хватило времени просмотреть мою небольшую заметку, снабжённую доказательствами? Или ты читаешь только большие статьи?![]()
Не отсылай меня в инет. Я там смотрел. Если бы там было, то мы бы не спорили. Ты не смог найти потаму, что нету.Книги Страуструпа смотри в интернете. Кстати, на той самой страничке, которую ты давал нам для ознакомления, снизу куча ссылок, в том числе и на главы из книг Страуструпа (кстати, если не знаешь, то это создатель языка С++). К сожалению я сходу не смог найти там ссылки на главы именно о вызове виртуальных функций в конструкторах, но ты можешь погуглить.
Перешёл на личности, т.к. нет доказательств ? Я хотел только узнать, почему ты решил, чо это vtbl и всё.Эммм, Airhand, твои слова только подтверждают твою необразованность. То, что все компиляторы Microsoft без исключения и ещё по крайней мере 95 процентов других компиляторов всех марок и мастей размещают указатель на таблицу виртуальных функций в первом машинном слове (для Win32 - это четыре байта) объекта - это общеизвестный факт.
Если я это говорил, то приведи цитату. Я с тем же успехом могу сказать, будто бы ты утверждал, что Земля плоская и находится на 4 китах/слонах.Именно ты, а также автор указанной тобой статьи, утверждаете, что виртуальные таблицы изменяются во время выполнения. Пример показывает, что это не так.
Я так понял, ты не знаеш что это и только предположил.Посмотрите на этот самолёт. Видите, у него есть руль, как и у моей игрушечной машинки. Вы что, глупы и ничего не понимаете? Никакой это не самолёт - это автомобиль!
Опять переход на личности, что нет доказательств ?Согласен, я поспешил с выводом, что пример понятен всем. Он понятен только знатокам С++. Собственно, знатокам эта статья и адресовалась.
Airhand, зачем ты споришь, не понимая толком о чём идёт речь? По твоим постам я вижу, что у тебя сейчас в голове каша - это видно и по постоянной неточной или ошибочной терминологии и по тому, как твои взгляды резко меняются от одного сообщения к другому. Возможно, эта каша со временем кристаллизуется в академические знания, но пока ты лишь напрасно надрываешься, пытаясь предстать перед всеми знающим человеком и с каждым постом, сам того не подозревая, всё более оголяя свою невежественность.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
#define while if
Оптимизация по размеру:
#define struct union
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Мы писали сообщения параллельно. Твоей дописки после текста "Добавлено сообщение" ещё не было." писал(а):Это ты называеш себя образованным человеком и не знаеш кто такой Ален Голуб ? Я твою заметку даже разобрал, о чём и выписал кучу замечаний.
Послушай, я не знал раньше никакого Алана Голуба, а после того, как прочитал его статью, то понял, что он мне не будет интересен и в будущем. Об этом человеке нет статьи на Википедии, он не засветился ни в одном серьёзном труде по C++. Почему ты считаешь, что любому программисту необходимо знать этого человека и, более того, настаиваешь, что если я его не знаю, то не профессионал? А ты знал Алана Голуба до того, как прочёл ту статью?
Может я, конечно, и правда непрофессионал по сравнению с теми же Страуструпом или Мейерсом, но уж никак не от того, что не знаком с Голубом

ОК, на личности больше переходить не буду. То, что это vtl, решал не я, это решили разработчики компилятора VC++." писал(а):Перешёл на личности, т.к. нет доказательств ? Я хотел только узнать, почему ты решил, чо это vtbl и всё.
Хочешь цитату, где ты говорил, что таблица меняется во время исполнения? Таких цитат было много. Вот одна из последних:" писал(а):Если я это говорил, то приведи цитату. Я с тем же успехом могу сказать, будто бы ты утверждал, что Земля плоская и находится на 4 китах/слонах.
Или инициализация не подразумевает внесение значения?" писал(а):Я писал о том, что таблица виртуальных функций инициализируется в последнем действии конструктора, а не до него.
Структура виртуальной таблицы устаканилась уже давно и является идентичной практически на всех компиляторах. Своё сообщение я писал с долей сомнения, постоянно задавая вопросы от несуществующего читателя и придираясь к своим собственным выводам, ради стилистики. Повествование в таком ключе, как правило, позволяет избежать массы вопросов в будущем, так как все они будут оговорены и снабжены ответами в процессе написания заметки. Сам я ни в чём не сомневался. Я могу рассказать и другие тонкости, которые познал с помощью расширения подобной программы в прошлом, но это не будет касаться темы вопроса." писал(а):Я так понял, ты не знаеш что это и только предположил.
Доказательство - это программа. Такие низкоуровневые детали реализации могут варьироваться от компилятора к компилятору. Я с самого начала написал, что говорю конкретно о линейке компиляторов от Microsoft. Твой же хвалёный Алан Голуб этого не сделал и, более того, написал несуразицу" писал(а):что нет доказательств

Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Какая жаркая дискуссия.
Я не сдержался. Ни с кем спорить не буду, ничего про это не знаю. Хотел только уточнить одну деталь.
Две цитаты уважаемого Airhand-а
К сожалению я не смог найти доказательств этой занимательной идеи в данной статье. Не могли бы вы уточнить этот момент? Мне очень хотелось бы увидеть это, чисто для себя и может нос кому утереть в следующий раз.
Я не сдержался. Ни с кем спорить не буду, ничего про это не знаю. Хотел только уточнить одну деталь.
Две цитаты уважаемого Airhand-а
Airhand писал(а):BBB
Противоречие НЕ в том, в какой последовательности вызываются конструкторы. Я писал о том, что таблица виртуальных функций инициализируется в последнем действии конструктора, а не до него.
Похоже я единственный (кроме Arihand конечно) почитал эту статью, но к величайшему сожалению не нашел там где же: "Ален Голуб говорит, что таблица виртуальных функций создается/перезаполняется последним действием в конструкторе".Airhand писал(а): Вот ссылка по теме: http://www.cyberguru.ru/programming/cpp ... age50.html
Ален Голуб говорит, что таблица виртуальных функций создается/перезаполняется последним действием в конструкторе. Я вообще запутался.
К сожалению я не смог найти доказательств этой занимательной идеи в данной статье. Не могли бы вы уточнить этот момент? Мне очень хотелось бы увидеть это, чисто для себя и может нос кому утереть в следующий раз.
Этим не нужно хвастаться. Это всё равно как если бы литературовед сказал: "Я не знаю никакого Тургенева".Послушай, я не знал раньше никакого Алана Голуба, а после того, как прочитал его статью, то понял, что он мне не будет интересен и в будущем. Об этом человеке нет статьи на Википедии, он не засветился ни в одном серьёзном труде по C++. Почему ты считаешь, что любому программисту необходимо знать этого человека и, более того, настаиваешь, что если я его не знаю, то не профессионал? А ты знал Алана Голуба до того, как прочёл ту статью?
Профессионалы - те люди, которые живут со своей профессии. Тогда уже не специалист. Я этого не утверждал нигде, это всё ты выдумал.
Да я знал книгу Алена Голуба:
[RIGHT]
ВЕРЕВКА ДОСТАТОЧНОЙ ДЛИНЫ, [/RIGHT]
[RIGHT]ЧТОБЫ ВЫСТРЕЛИТЬ СЕБЕ В НОГУ
Правила программирования на С и С++
Ален И. Голуб[/RIGHT]
Инициализация - это, прежде всего, выделение памяти под объкт. А выделение памяти и внесение изменений в таблицу - это разные вещи.Или инициализация не подразумевает внесение значения?
Может это метка-заполнитель для функции сравнения. Или ты имееш спеку виртульной таблицы ?Структура виртуальной таблицы устаканилась уже давно и является идентичной практически на всех компиляторах. Своё сообщение я писал с долей сомнения, постоянно задавая вопросы от несуществующего читателя и придираясь к своим собственным выводам, ради стилистики. Повествование в таком ключе, как правило, позволяет избежать массы вопросов в будущем, так как все они будут оговорены и снабжены ответами в процессе написания заметки. Сам я ни в чём не сомневался. Я могу рассказать и другие тонкости, которые познал с помощью расширения подобной программы в прошлом, но это не будет касаться темы вопроса.
Hawk
А вот что сделает с ним компилятор:Похоже я единственный (кроме Arihand конечно) почитал эту статью, но к величайшему сожалению не нашел там где же: "Ален Голуб говорит, что таблица виртуальных функций создается/перезаполняется последним действием в конструкторе".
Код: Выделить всё
[B]int[/B] _employee__print( employee *this ) { /* ... */ }
[B]int[/B] _employee__cmp ( employee *this, [B]const[/B] storable *ref_r ) { /* ... */ }
_vtab _employee_vtable =
{
_employee__print,
_storable_virtf, // [I]Тут нет замещения в производном классе, поэтому[/I]
// [I]используется указатель на функцию базового класса[/I].
_employee_cmp
};
[B]typedef[/B] [B]struct[/B] employee
{
_vtab *_vtable; // [I]Генерируемое компилятором поле данных.[/I]
[B]int[/B] stuff; // [I]Поле базового класса[/I].
[B]int[/B] derived_stuff; // [I]Поле, добавленное в объявлении производного класса[/I].
}
employee;
_employee__ctor( employee *this ) // [I]Конструктор по умолчанию, генерируемый[/I]
{ // [I]компилятором.[/I]
_storable_ctor(); // [I]Базовые классы инициализируются[/I]
// [I]в первую очередь[/I].
_vtable = _employee_vtable; // [I]Создается таблица виртуальных функций[/I].
}
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
#define while if
Оптимизация по размеру:
#define struct union