有些事情我不清楚,我想提请你注意,请检查这些代码片段:
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定义为普通的非模板类,这个代码不起作用的原因是什么?由于从const到非const指针到城市的转换暂定,转换失败,为什么?
这是错误打印:
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吗?
谢谢大家。
答案 0 :(得分:4)
它是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),它也可以在没有模板的情况下工作。