有没有办法使用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无法实现此行为,为何禁止使用?
答案 0 :(得分:2)
您的问题与CRTP无关,但具有多重继承。 Child
从其基类继承ptr_t
,两种类型都不同:shared_ptr<Parent>
与shared_ptr<Child>
。因此,编译器无法通过Child::ptr_t
中的main
找出您的意思。
正如您所指出的,您必须使用typedef
中的Child
手动修复此问题(但Pointable
基类无用)。
class Child : public Parent,
public Pointable<Child> {
public:
typedef Pointable<Child>::ptr_t ptr_t;
答案 1 :(得分:0)
假设Child是从Parent公开派生的,没有办法在每个中定义相同的typedef,而不在Child的定义中放置内容。但是,如果定义了继承,Child将从Parent继承错误的typedef。
一种可能性是定义特征类
template<typename T> class Traits
{
public:
typedef std::shared_ptr<T> ptr_t;
}
显然在这种情况下,由于引用Traits :: ptr_t比Child :: ptr_t长,因此不会给你带来太大的好处。 (但是如果你有很多typedef,或者你希望以后能够更改指针类型,它可能会有用。)
答案 2 :(得分:0)
如果Child仅从Parent派生(并且不是来自Pointable的显式),则Pointable
与Pointabe<Parent>
完全相同,因为它是父级,而父级是Pointable。
Parent :: ptr_t可以保存Child的实例,导致Child isa Parent(至少在代码意义上)。
我不知道你想用ptr_t做什么。您丢失了确切的类型,但您可以尝试在层次结构中执行dynamic_cast
。也许这就够了。