Есть кое-что непонятное для меня, я хочу обратить ваше внимание, пожалуйста, проверьте эти фрагменты кода:
template< typename DerivedClass >
class construction_management
{
city* this_city;
public:
construction_management()
{
this_city = static_cast< city* >(this);
}
~construction_management();
};
Я намеренно удалил весь ненужный код, пожалуйста, посмотрите на конструктор, который делает статическое приведение указателя this к типу city, который определен следующим образом:
class city : public construction_management< city >
{
public:
public:
city( const string& name, const string& owner );
};
Класс намеренно пустой, так как я думаю, что здесь ничего не может быть. Хочу, чтобы я не смог на 100% понять, что здесь происходит, g ++ 4.7.2 печатает без предупреждений или ошибок на этапе компиляции, и всякий раз, когда я использую указатель ‘this_city’, я могу получить доступ ко всем публичным членам города, сам объект выглядит непротиворечивым, поскольку все переменные правильно инициализированы и содержат всегда действительные данные.
Что я хотел бы знать, почему этот код не работает, если я определяю construction_management как простой не шаблонный класс? Сбой приведения из-за предварительного преобразования из константного в неконстантный указатель на город, почему?
Это ошибка печати:
game.hpp: In constructor 'city_manager::construction_management::construction_management()':
game.hpp:164:41: error: invalid static_cast from type 'city_manager::construction_management* const' to type 'city_manager::city*'
А зачем работать, если construction_management — это шаблон? Это своего рода CRTP?
Спасибо вам всем.
Это CRTP, и он работает из-за ленивого создания шаблона.
Линия:
this_city = static_cast< city* >(this);
требует this
быть конвертируемым в city*
, Это работает, если city
происходит от construction_management
, Однако базовые классы должны иметь полные объявления перед производными классами, поэтому есть только один способ написать это:
//template code may or may not be present
class construction_management {...};
//maybe more code here
class city: public construction_management {...};
Если базовый класс не является шаблоном, он создается, когда компилятор впервые видит код. Затем компилятор запускается в конструктор, он не знает, что city
происходит от construction_management
(или даже какой city
есть, если он не был объявлен как неполный тип) и сдается.
Однако, если базовый класс является шаблоном, он создается при объявлении наследования (в любом случае, где-то в это время, я не эксперт в этом). На этом этапе компилятор знает, что city
происходит от construction_management<city>
и все работает.
По тем же причинам он также работает без шаблона, если вы перемещаете определение конструктора в файл, который компилируется позже (скорее всего из .h в .cpp).
Других решений пока нет …