2012-01-12 95 views
6

我的問題很簡單。我有一個類模板,它包含一個指向動態分配類型的指針。我想重載間接運算符,以便使用 - >運算符引用類模板實例,這樣我就可以重定向,就好像我使用直接包含的指針一樣。在C++中重載間接運算符

​​

創建某種類型的MyClass的:

MyClass<SomeObject> instance; 

所以我想是不是不必鍵入:

instance.ptr->someMemberMethod(); 

我只需鍵入:

intance->someMemberMethod(); 

即使你instance不是ap它的行爲就好像它是包含的指針instance一樣。如何通過重載運營商來彌合這一差距?

+0

現代C++設計(安德烈Alexandrescu)有一些關於這個問題真的很好的信息,如果你想更深入。 – 2012-01-12 19:25:33

回答

11

您只需重載operator->operator*

template<class T> 
class MyClass 
{ 
    T* ptr; 

public: 
    T* operator->() { 
     return ptr; 
    } 

    // const version, returns a pointer-to-const instead of just a pointer to 
    // enforce the idea of the logical constness of this object 
    const T* operator->() const { 
     return ptr; 
    } 

    T& operator*() { 
     return *ptr; 
    } 

    // const version, returns a const reference instead of just a reference 
    // to enforce the idea of the logical constness of this object 
    const T& operator*() const { 
     return *ptr; 
    } 
}; 

需要注意的是,由於語言的創造者設計的決定,你不能超載.操作。

此外,您可能會認爲operator*會使運算符超載,而不是解引用運算符。但是,情況並非如此,因爲乘法運算符只有一個參數(而解引用運算符不帶參數),因此編譯器可以知道哪個是哪個參數。

最後,請注意,operator->返回一個指針,但operator*返回一個引用。意外混淆它們很容易。

+0

很好的答案。但是你能分辨const-version和non-const之間的區別嗎?我什麼時候可以使用他們兩個? – SimpleGuy 2016-08-18 03:19:06

+0

另外爲什麼需要重載' - >'和'*'。爲什麼只是重載' - >'還不夠? – SimpleGuy 2016-08-18 03:40:21

+0

@SimpleGuy你的類的用戶通常期望'foo-> bar'等同於'(* foo).bar'。讓他們不同會震驚許多人。 – Bernard 2017-06-26 12:11:28

5

超載的->操作:

template <typename T> class MyClass 
{ 
    T * p; 
public: 
    T  * operator->()  { return p; } // #1 
    T const * operator->() const { return p; } 
}; 

注意重載不發生變異的對象;儘管如此,我們決定讓#1非const,以便將對象的持久性傳遞給指出者。這有時被稱爲「深度傳播」或這種類型的東西。語言D需要更多。

+0

「我們決定讓#1非常量」 - 至少,如果我們願意的話,我們可以。標準的智能指針並不是基本上出於同樣的原因,可以通過'T * const'修改'T'類型的對象。你所做的取決於'instance'是否是「邏輯上」對另一個對象的間接引用(在這種情況下模仿標準的智能指針)或者不是(在這種情況下詛咒Bjarne你不能重載'operator.')。 – 2012-01-12 19:36:26

+1

@SteveJessop:我認爲,「我們」就像「你和我,在這次C++的旅程中」,而不是「我們所有意見的現存統治者」。對不起,舊習慣:-) – 2012-01-12 19:38:15

3

成員訪問運算符也可以被重載返回一個指向對象被訪問:

T * operator->() {return ptr;} 
T const * operator->() const {return ptr;} 

您也可能希望在尊重運營商,使其感覺更加像一個指針;這將返回一個參考,而不是:

T & operator*() {return *ptr;} 
T const & operator*() const {return *ptr;}