1

我有一些不清楚的地方希望引起您的注意,请检查这些代码片段:

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 到指向 city 的非 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 吗?

谢谢你们。

4

1 回答 1

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(或者甚至 acity是什么,如果它没有被声明为不完整的类型),并放弃。

但是,如果基类是模板,它会在声明继承时被实例化(无论如何,我不是这方面的专家)。那时,编译器知道它city是从 派生的construction_management<city>,并且一切正常。

出于同样的原因,如果您将构造函数定义移动到稍后编译的文件(很可能从 .h 到 .cpp),它也可以在没有模板的情况下工作。

于 2013-01-03T11:42:37.620 回答