Aroch
> При конструкторах виртуальный метод не вызвать
Ещё раз повторюсь - виртуальный метод вызывается без проблем. Проблема может заключаться в том, что сам объект во время работы конструктора - принадлежит классу именно этого конструктора, и виртуальный метод будет вызван соответствующий. Если у нас есть классы Base и Derived: Base, и мы инициализируем экземпляр Derived d - пока будет выполняться конструктор базового класса, typeof(d) == typeid(Base). И только после того, как базовый конструктор завершит работу, отработают конструкторы полей дерайведа, и сам конструктор Derived::Derived войдёт в свой скоуп - только тогда виртуальная таблица объекта обновится, и он станет typeof(d) == typeid(Base).
struct Typed { virtual char const* getType() = 0; }; void printTypeOf( char const* where, Typed* obj) { // самый настоящий обычный виртуальный вызов // можем эту функцию вообще скомпилировать отдельно и вынести в длл printf( "In %s, the type of %#18llx is %s\n", where, ( intptr_t)obj, obj->getType( )); } struct Base: Typed { virtual char const* getType( ) override { return "Base"; } Base( ) { printTypeOf( "Base::Base", this); // всегда будет печатать //> In Base::Base, the type of 0xbebebebe is Base } ~Base( ) { printTypeOf( "Base::~Base", this); // всегда будет печатать //> In Base::~Base, the type of 0xbebebebe is Base } }; struct Derived: Base { virtual char const* getType( ) override { return "Derived"; } Derived( ) { printTypeOf( "Derived::Derived", this); // всегда будет печатать //> In Derived::Derived, the type of 0xbebebebe is Derived } ~Derived( ) { printTypeOf( "Derived::~Derived", this); // всегда будет печатать //> In Derived::~Derived, the type of 0xbebebebe is Derived } };
Если бы виртуальный метод было "не вызвать" - то вызов printTypeOf, который содержит вызов к виртуальной функции, закрашил бы программу. Но это не так - он отрабатывает, и у него даже есть чётко определённое поведение (без УБ).
Ну то есть особенность вызова виртуальных функций в конструкторах и деструкторах (а также в любых методах, которые вызваны из них) кратко можно описать так:
в конструкторах, деструкторах класса T и любых методах, вызванных из них, виртуальные функции вызываются так, как будто порожденные от класса T классы еще не были определены.
Имбирная Ведьмочка
> Если бы виртуальный метод было "не вызвать" - то вызов printTypeOf, который
> содержит вызов к виртуальной функции, закрашил бы программу. Но это не так - он
> отрабатывает, и у него даже есть чётко определённое поведение (без УБ).
ты же сам видишь как он обрабатывает, что вызывается функция класса который был создан, а не та которого должны создать. С точки зрения класса который уже успел создаться если у тебя более длинная цепочка наследования, то да произошел вызов виртуальной функции. Только дальше она не пойдет. Как бы тут нет ничего противоречивого с тем что ранее было сказано.
Dmitry_Milk
> никогда с этим не сталкивался...
для интерфейсов там вообще "pure virtual function call" получится
это хорошо что не сталкивался, наследование зло
nes
> std::array
На мой взгляд какой-то недоделанный класс получился.
#!
> для интерфейсов там вообще "pure virtual function call" получится
Хыы, да, шляпа. И ведь компилятор даже не сообразил, что чистая виртуальная функция вызывается в деструкторе опосредованно через intermediate (если напрямую вызовать - при компиляции сообразил).
0xBADCODE
> На мой взгляд какой-то недоделанный класс получился.
это замена сырым массивам. Оверхед нулевой, а удобства при использовании имеются.
std::vector и std::string в игровом движке - стоит использовать или писать велосипед, подводные, аргументы?
Aroch
> удобства при использовании имеются.
Удобно было бы, если бы это имело интерфейс вектора с постоянным капасити.
0xBADCODE
А движок свой или готовый? Если свой, то вектор и строка тоже должны быть своими. Со своим аллокатором.
1 frag / 2 deaths
> 0xBADCODE
> А движок свой или готовый?
Пишу свой.
>Если свой, то вектор и строка >тоже должны быть
> своими. Со своим аллокатором.
Почему?
0xBADCODE
> Удобно было бы, если бы это имело интерфейс вектора с постоянным капасити.
а метода beep() там не должно быть? Ну чтобы удобно было, сравнил размер и сразу beep() под рукой в случае чего, не?
Aroch
> а метода beep() там не должно быть?
Достаточно эксепшна. Мне приходилось заводить отдельную переменную для учета реально хранящегося в std::array числа элементов, хотя до знакомства с ним я полагал, что можно будет просто воспользоваться push_back() и size().
Очередной глупый вопрос, как очистить массив
struct TilesCell { TilesCell() { memset( tiles, 0, SizeMapZ * SizeMap* SizeMap); } Tile* tiles[SizeMapZ][SizeMap][SizeMap]; };
Не работает - какой-то элемент не обнуляется (вылетает по 0xFFFFFFF - что в дебаге как признак что элемент не занулен)
war_zes
>
> memset(tiles, 0, SizeMapZ * SizeMap* SizeMap);
memset требует размер в байтах, а не количество элементов в массиве, разве нет?