2012-02-02 10 views
1

Есть ли способ определить тип с тем же именем для классов в отношениях наследования с помощью CTRP? Я попробовал следующий код, но получил error: member 'ptr_t' found in multiple base classes of different types от clang++.typedef с CRTP не работает, когда используется наследование

#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, почему это запрещено?

ответ

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; 
+0

Выяснилось. Большое спасибо! – mooz

0

происходит Предполагая, что Ребенок публично от Родителя, нет никакого способа, чтобы иметь такую ​​же ЬурейеЕ определяется по-разному в каждом без положить что-то в определении ребенка. Однако вы определяете наследование, Child наследует неправильный typedef от Parent.

Одной из возможностей были бы определить класс черты

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

Очевидно, что в этом случае не получить вам много, так как со ссылкой на Признаки :: ptr_t больше, чем дети :: ptr_t. (Но это может быть полезно, если у вас много typedefs, или если вы захотите изменить тип указателя позже.)

0

Если дочерний элемент имеет только родительский элемент (и не явный из Pointable), это Pointable а точнее Pointabe<Parent>, вызывают его родительский и родительский.

Родитель :: ptr_t может содержать экземпляр Child, из-за которого ребенок является родителем (по крайней мере, в смысле кода).

Я не знаю, что вы хотите сделать с ptr_t. Вы теряете точный тип, но можете попытаться сделать dynamic_cast по иерархии. Возможно, этого достаточно.