1

CTRPを使って継承関係にあるクラスに同名の型を定義する方法はありますか? 次のコードを試しましたが、error: member 'ptr_t' found in multiple base classes of different typesから取得しましたclang++

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

もちろん、次のものは問題ありません (ただし、冗長であり、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 を使用してこの動作を実現する方法がない場合、それが禁止されているのはなぜですか?

4

3 に答える 3

2

あなたの問題はCRTPとは何の関係もありませんが、多重継承とは関係ありません。 Childは両方の基本クラスから継承ptr_tされ、両方の型が異なります: shared_ptr<Parent>vs. shared_ptr<Child>. Child::ptr_tしたがって、コンパイラはinが意味する型を特定できませんmain

ご指摘のとおり、これは in を使用して手動で修正する必要がありtypedefますChild(Pointableただし、基本クラスは役に立たなくなります)。

class Child : public Parent,
              public Pointable<Child> {
public:
    typedef Pointable<Child>::ptr_t ptr_t;
于 2012-02-02T15:40:04.773 に答える
0

Child が Parent からのみ派生した (そして Pointable から明示的でない) 場合、それはPointable正確に aPointabe<Parent>であり、それは Parent であり、Parent は Pointable であるためです。

Parent::ptr_t は Child のインスタンスを保持できるため、Child は (少なくともコードの意味では) Parent になります。

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

于 2012-02-02T16:43:12.183 に答える
0

Child が Parent からパブリックに派生していると仮定すると、Child の定義内に何かを配置せずに、同じ typedef をそれぞれで異なるように定義する方法はありません。ただし、継承を定義すると、子は親から間違った typedef を継承します。

1つの可能性は、特性クラスを定義することです

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

Traits::ptr_t への参照は Child::ptr_t よりも長いため、明らかにこの場合はあまりメリットがありません。(ただし、多くの typedef がある場合や、後でポインターの型を変更できるようにしたい場合に便利です。)

于 2012-02-02T16:02:45.897 に答える