2012-02-02 19 views
1

CTRPを使用して継承関係のクラスに同じ名前の型を定義する方法はありますか?次のコードを試しましたが、error: member 'ptr_t' found in multiple base classes of different typesclang++になりました。継承を使用すると、CRTPのtypedefは機能しません

#include <iostream> 
#include <tr1/memory> 

template <typename T> class Pointable { 
public: 
    // define a type `ptr_t` in the class `T` publicly 
    typedef std::tr1::shared_ptr<T> ptr_t; 
}; 

class Parent : public Pointable<Parent> { 
public: 
    Parent() { 
     std::cout << "Parent created" << std::endl; 
    } 

    ~Parent() { 
     std::cout << "Parent deleted" << std::endl; 
    } 
}; 

class Child : public Parent, 
       public Pointable<Child> { 
public: 
    Child() { 
     std::cout << "Child created" << std::endl; 
    } 

    ~Child() { 
     std::cout << "Child deleted" << std::endl; 
    } 
}; 

int main(int argc, char** argv) 
{ 
    Child::ptr_t child_ptr(new Child()); 
    Parent::ptr_t parent_ptr(new Parent()); 

    return 0; 
} 

もちろん、次のものはOKです(ただし、重複してDRYの原則に反する)。

class Parent { 
public: 
    typedef std::tr1::shared_ptr<Parent> ptr_t; 

    Parent() { 
     std::cout << "Parent created" << std::endl; 
    } 

    ~Parent() { 
     std::cout << "Parent deleted" << std::endl; 
    } 
}; 

class Child : public Parent { 
public: 
    typedef std::tr1::shared_ptr<Child> ptr_t; 

    Child() { 
     std::cout << "Child created" << std::endl; 
    } 

    ~Child() { 
     std::cout << "Child deleted" << std::endl; 
    } 
}; 

CRTPを使用してこの動作を実現する方法がない場合、なぜそれが禁止されていますか?

答えて

2

問題はCRTPとは関係ありませんが、複数の継承があります。 Childは、両方の基本クラスからptr_tを継承し、両方のタイプが異なる:shared_ptr<Parent>shared_ptr<Child>です。そのため、コンパイラは、Child::ptr_tを意味するタイプをmainに見つけることはできません。

typedefChildで手動で修正する必要があります(ただし、Pointableの基本クラスは役に立たなくなります)。

class Child : public Parent, 
       public Pointable<Child> { 
public: 
    typedef Pointable<Child>::ptr_t ptr_t; 
+0

説明しました。どうもありがとう! – mooz

0

子供が親から公に導き出されると仮定すると、子供の定義の中に何かを入れずに、それぞれで異なって定義された同じのtypedefを持ってする方法はありません。ただし、継承を定義すると、ChildはParentから間違ったtypedefを継承します。

一つの可能​​性はトレイトを参照するので、ずっとあなたを獲得していません。この場合は明らかに

template<typename T> class Traits 
    { 
    public: 
     typedef std::shared_ptr<T> ptr_t; 
    } 

特性クラスを定義することです:: ptr_tは長い子供より:: ptr_t。 (しかし、多くのtypedefがある場合や、後でポインタタイプを変更できるようにしたい場合に便利です)

0

子が親から派生したもので、Pointableから派生したものではない場合はPointable正確にはPointabe<Parent>であり、それはParentであり、ParentはPointableである。

Parent :: ptr_tはChildのインスタンスを保持できます(少なくともコードの意味では)Child isa Parentを引き起こします。

私はあなたがptr_tで何をしたいのか分かりません。あなたは正確なタイプを失いますが、dynamic_castを階層の上に置こうとすることができます。おそらくそれで十分でしょう。

関連する問題