2012-02-02 59 views
1

有沒有什麼方法可以通過使用CTRP來爲繼承關係中的類定義一個同名的類型?我嘗試了下面的代碼,但從clang++得到error: member 'ptr_t' found in multiple base classes of different types當使用繼承時,使用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>。因此,編譯器無法確定mainChild::ptr_t的含義。

正如你所指出的那樣,你必須使用typedefChild中手動解決這個問題(儘管你的Pointable基類沒用)。

class Child : public Parent, 
       public Pointable<Child> { 
public: 
    typedef Pointable<Child>::ptr_t ptr_t; 
+0

想通了。非常感謝! – mooz 2012-02-02 16:18:50

0

承擔起子女衍生公開從父,有沒有辦法有不同的定義各不把一些兒童的定義中相同的typedef。但是,您定義了繼承,Child將從Parent繼承錯誤的typedef。

一種可能性是定義一個traits類

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

顯然,在這種情況下不會獲得你多少,因爲參照性狀:: ptr_t比兒童:: ptr_t更長。 (但是如果你有很多類型定義,或者你希望能夠稍後改變指針類型,它可能會很有用。)

0

如果孩子只從父項派生(而不是從顯式指向),它是一個Pointable準確地說是一個Pointabe<Parent>,導致它是一個父母,而父母是一個指針。

Parent :: ptr_t可以容納Child的一個實例,導致Child isa Parent(至少在代碼意義上)。

我不知道你想用ptr_t做什麼。你沒有確切的類型,但你可以嘗試在層次結構上做一個dynamic_cast。也許這就夠了。