简体   繁体   中英

Object slicing when using CRTP

I am stuck with an object slicing problem when using CRTP. The following mock illustrates my problem.

#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;
}

Compiling the above code gives me the following error:

main.cpp: In function 'int main()':
main.cpp:47:16: error: 'class CrtpGenr' has no member named 'funct1'
 crtp_obj1->funct1();
            ^
main.cpp:48:16: error: 'class CrtpGenr' has no member named 'funct2'
 crtp_obj1->funct2();

I would like to be able to cast the CrtpDirv1 and CrtpDirv2 classes to CrtpGenr. This is so that I can define a container of type CrtpGenr to hold objects of either CrtpDirv1 or CrtpDirv2. What am I doing wrong?

*crtp_obj1 is of type CrtpGenr - as you claim in line 48. And this is in fact true, since the whole shebang derives from CrtpGenr . So the static_casts compile.

But you've got the inheritance thing backwards, methinks. Look at the definition of CrtpGenr :

class CrtpGenr
{
};

It has no methods. Why would you expect the compiler to allow to you try to call one on that object?!

If you cast so that you can put objects of some common base type into a container (eg `std::list'), then you can do this, but when you want to call specific methods on that object, you'd need to tell the compiler what kind of object it really is by casting that pointer back to the type you created.

You may want to look into inheritance and polymorphism a little more deeply. For example, perhaps CrtpGenr class can have a virtual method funct1() that the derived classes implement.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM