2012-02-02 3 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; 
} 

당연히 다음 중 하나는 정상입니다 (단, 중복되어 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

공개적으로 부모에서 자식의 정의 내부에 뭔가를주지 않고 다른 각에서 정의 된 같은 형식 정의를 할 수있는 방법이 없습니다. 그러나 상속을 정의하지만 Child는 Parent로부터 잘못된 typedef를 상속받습니다.

하나의 가능성은 특색 참조 : ptr_t는 더 이상 아이 :: ptr_t 이상이기 때문에, 많이 얻을하지 않습니다이 경우에 특성 클래스를 분명히

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

을 정의하는 것입니다. (그러나 typedef가 많이 있거나 나중에 포인터 유형을 변경할 수 있기를 원할 때 유용 할 수 있습니다.)

0

하위 항목은 부모로부터 만 파생되었으며 (Pointable에서 명시하지 않은 경우) Pointable입니다. Pointabe<Parent>으로 지정하고 부모가 부모이고 상위가 Pointable 인 원인이됩니다.

Parent :: ptr_t는 Child의 인스턴스를 보유 할 수 있으므로 Child isa Parent (최소한 코드의 의미에서)를 발생시킬 수 있습니다.

나는 당신이 ptr_t로 무엇을하고 싶은지 모른다. 정확한 유형을 잃어 버렸지 만 dynamic_cast 계층 구조를 시도 할 수 있습니다. 아마도 그게 충분합니다.

관련 문제