从基类到派生的静态转换

时间:2013-01-03 11:20:56

标签: c++ templates inheritance crtp static-cast

有些事情我不清楚,我想提请你注意,请检查这些代码片段:

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吗?

谢谢大家。

1 个答案:

答案 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),它也可以在没有模板的情况下工作。