статическое приведение из базового класса к производному

Есть кое-что непонятное для меня, я хочу обратить ваше внимание, пожалуйста, проверьте эти фрагменты кода:

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?

Спасибо вам всем.

1

Решение

Это 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).

4

Другие решения

Других решений пока нет …