2012-01-12 39 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;}