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>shared_ptr<Child>. 因此,编译器无法确定您所说的Child::ptr_tin是哪种类型main

正如您所指出的,您必须使用typedefin手动修复此问题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 公开派生的,如果不将某些内容放入 Child 的定义中,就无法在每个中以不同方式定义相同的 typedef。无论您如何定义继承,Child 都会从 Parent 继承错误的 typedef。

一种可能性是定义一个特征类

  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 回答
0

如果 Child 仅从 Parent 派生(而不是明确地从 Pointable 派生),则它是 aPointable准确地说是 a Pointabe<Parent>,因为它是 Parent,而 Parent 是 Pointable。

Parent::ptr_t 可以保存 Child 的实例,导致 Child 是 Parent(至少在代码的意义上)。

我不知道你想用 ptr_t 做什么。你失去了确切的类型,但你可以尝试做一个dynamic_cast向上的层次结构。也许这就足够了。

于 2012-02-02T16:43:12.183 回答