使用CRTP时的对象切片

时间:2016-03-30 06:12:13

标签: c++ crtp object-slicing

使用CRTP时,我遇到了对象切片问题。以下模拟说明了我的问题。

org.clojure/tools.reader

编译上面的代码会出现以下错误:

#include <memory>

class CrtpGenr
{
};

template<class t_object>
class CrtpBase : public CrtpGenr
{
    public:
        static
        auto create() -> std::unique_ptr<t_object> {
            return(std::unique_ptr<t_object>(new t_object));
        }
        void funct1(){}
};

class CrtpDirv1 : public CrtpBase<CrtpDirv1>
{
    public:
        void funct2(){}
};

class CrtpDirv2 : public CrtpBase<CrtpDirv2>
{
    public:
        void funct2(){}
};


int main()
{
/*
    // This works
    std::unique_ptr<CrtpDirv1> crtp_obj = CrtpDirv1::create();
    crtp_obj->funct1();
    crtp_obj->funct2();
*/

    std::unique_ptr<CrtpGenr> crtp_obj1 = static_cast<std::unique_ptr<CrtpGenr>>(CrtpDirv1::create());
    std::unique_ptr<CrtpGenr> crtp_obj2 = static_cast<std::unique_ptr<CrtpGenr>>(CrtpDirv2::create());
    crtp_obj1->funct1();
    crtp_obj1->funct2();

    return 0;
}

我希望能够将CrtpDirv1和CrtpDirv2类转换为CrtpGenr。这样我就可以定义一个CrtpGenr类型的容器来保存CrtpDirv1或CrtpDirv2的对象。我做错了什么?

1 个答案:

答案 0 :(得分:0)

*crtp_obj1的类型为CrtpGenr - 正如您在第48行所声称的那样。事实上这是正确的,因为整个shebang来自CrtpGenr。所以static_casts编译。

但是,你已经将继承的东西倒退了。查看CrtpGenr

的定义
class CrtpGenr
{
};

它没有方法。为什么您希望编译器允许您尝试在该对象上调用一个?!

如果你进行转换以便可以将某些公共基类型的对象放入容器(例如`std :: list&#39;),那么你可以这样做,但是当你想在该对象上调用特定的方法时,你需要通过将指针强制转换回你创建的类型来告诉编译器它是什么类型的对象。

您可能希望更深入地研究继承和多态。例如,也许CrtpGenr类可以具有派生类实现的虚方法funct1()