2013-04-25 95 views
1

很抱歉的壞稱號基類的賦值運算符......我有一個基類,如:我可以在返回子類類型

template<class T> 
class GPtr 
{ 
public: 
    typedef T BaseType; 

    GPtr& operator=(const BaseType& rhs) 
    { 
     ... 
    } 
}; 

我經常想使子類的專門化,如:

class GraphicPtr : public GPtr<Graphic> 
{ 
... 
}; 

但是我的基類賦值運算符仍返回GPtr<Graphic>沒有GraphicPtr,它的惱人必須複製粘貼代碼的情況下,核心賦值運算符的功能應該在以後更改。

是否有一種簡潔的方式來定義基類賦值運算符,以便返回正在使用的實際類的類型?

+0

爲什麼不寫函數,真的可以在所有派生類中進行賦值和調用? – ForEveR 2013-04-25 09:08:12

+0

這裏解決的真正問題是什麼?不是解決方案的語法問題,而是解決方案似乎具有返回對派生類型的引用的賦值運算符的實際問題。有幾件事情不清楚,比如爲什麼'GPtr <> :: operator ='接受一個'T'參數(錯誤地命名爲'BaseType'),你想達到什麼目的? – 2013-04-25 13:12:45

回答

1

在C++中,基類不知道它的子類。您可以添加一個將作爲派生類的模板參數並使用它。

template<class T, class Derived> 
class GPtr 
{ 
public: 
    typedef T BaseType; 

    Derived& operator=(const BaseType& rhs) 
    { 
     ... 
    } 
}; 
+0

我想知道這是否可能。但是,如果我想直接使用'GPtr',但不總是在子類中,會發生什麼? – 2013-04-25 09:15:15

+0

我試圖使第二個參數GPtr ,但它是不可能的,因爲在這裏我們需要無限的專業化:GPtr >>>。也許在這裏你應該嘗試不同的東西:) – lisyarus 2013-04-25 09:32:51

+1

這就是我看到的同樣的問題。它似乎應該是可能的東西,但我不太瞭解模板 – 2013-04-25 09:34:56

1

也許你可以用CRTP代替?

#include <iostream> 

template<class Derived> 
class GPtr 
{ 
public: 
    typedef Derived DerivedType; 

    GPtr& operator=(const GPtr& rhs) 
    { 
     std::cout << "GPtr::operator=" << std::endl; 

     return *this; 
    } 
}; 

class GraphicDerived : public GPtr<GraphicDerived> 
{ 
    public: 

     GraphicDerived& operator=(const GraphicDerived& rhs) 
     { 
      std::cout << "GraphicDerived::operator=" << std::endl; 
      // Inheiriting shadows the name of the base operator= which 
      // needs to be explicitly called. 
      GPtr<GraphicDerived>::operator=(rhs); 
      return *this; 
     }; 
}; 

class Graphic {}; 

using namespace std; 

int main() 
{ 


    GraphicDerived one; 
    GraphicDerived two; 

    cout << "derived assignment: " << endl; 
    one = two; 

    GPtr<Graphic> ptrOne; 
    GPtr<Graphic> ptrTwo; 

    cout << "GPtr assignment stnadalone : " << endl; 

    ptrOne = ptrTwo; 
}; 

結果與:

derived assignment: 
GraphicDerived::operator= 
GPtr::operator= 
GPtr assignment stnadalone : 
GPtr::operator= 
+0

也許我誤讀,但似乎有兩個問題... 1)我仍然必須在派生類中編寫一個單獨的賦值運算符... 2)基數類已經在它包裝的類型上模板化,它與子類 – 2013-04-25 09:34:02

+1

不相同。1)如果派生類與基類相比具有附加屬性,則在派生類中添加單獨的賦值運算符是有意義的。 2)好吧,我明白你的意思了,這裏有個反問題:你究竟想達到什麼目的? – tmaric 2013-04-25 09:37:42

1

你所要求的並沒有真正意義。在分配基礎對象時,它不可能知道它被調用的派生類型中可能有無限多個派生類型,因此無法在每種情況下返回不同的類型。此外,即使這是可能的,也不可能在真實的代碼中使用它。

C++解決一切,但在運行時多態性電話,甚至多態調用它只是延遲找到確切覆蓋,但沒有簽名(即即使協變返回類型,基本覆蓋的返回類型將被使用。

從技術上講,可以使用或不使用模板,所有這些都表現出相同的核心問題:基類只能是單一類型的基類,由賦值運算符返回的類型,限制可用性爲基地類。

你想解決什麼是真正的問題?

您採取的方法似乎不合適。如果你解釋了你正在努力達到的目標,那麼人們可以建議其他方法會更好。

+0

正是我所評論的。我以爲我錯過了一些東西。 1+。 – tmaric 2013-04-25 12:05:00

+0

儘管這不是一個正常的繼承,但它是模板化的 - 所以對於每個特定的變體,都會創建一個完全獨立的類,而不是具有真正的基類方法。因此賦值運算符在每種情況下都是相同的,適用於涉及的模板類型。 @lisyarus'的答案與我所做的最接近 – 2013-04-25 14:42:26

+0

@John:它是否是模板幾乎是正交的。沒有任何東西可以抑制'struct a:base {}; struct b:base {};'。除非這個限制是你設計的一部分(你可以在C++ 11中強制執行,但是不會在你的代碼中執行)。如果是這樣的話,那麼你就是在濫用繼承,並且應該用組合來代替,沒有理由不將'GPtr '作爲'GraphicDerived'的成員,並且我仍然沒有看到賦值......隱式定義的不工作的原因是什麼? (爲什麼?) – 2013-04-25 15:52:04