0

CRTP を使用すると、オブジェクトのスライスの問題が発生します。次のモックは、私の問題を示しています。

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

上記のコードをコンパイルすると、次のエラーが発生します。

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();

CrtpDirv1 および CrtpDirv2 クラスを CrtpGenr にキャストできるようにしたいと考えています。これは、タイプ CrtpGenr のコンテナーを定義して、CrtpDirv1 または CrtpDirv2 のいずれかのオブジェクトを保持できるようにするためです。私は何を間違っていますか?

4

1 に答える 1

0

*crtp_obj1あなたが48行目で主張しているように、タイプです。CrtpGenrシバン全体が CrtpGenrしたがって、 static_casts がコンパイルされます。

しかし、あなたは継承のことを逆に持っていると思います。の定義を見てくださいCrtpGenr:

class CrtpGenr
{
};

メソッドはありません。そのオブジェクトで呼び出しを試みることをコンパイラが許可することを期待するのはなぜですか?!

共通の基本型のオブジェクトをコンテナー (例: std::list) に入れることができるようにキャストする場合は、これを行うことができますが、そのオブジェクトで特定のメソッドを呼び出したい場合は、次のようにする必要があります。そのポインターを作成した型にキャストして戻すことにより、実際のオブジェクトの種類をコンパイラーに伝えます。

継承とポリモーフィズムをもう少し深く調べたいと思うかもしれません。たとえば、おそらくクラスは、派生クラスが実装するCrtpGenr仮想メソッドを持つことができます。funct1()

于 2016-03-30T06:37:17.863 に答える