2012-04-28 20 views
5

比方说,我们有这个A级:如何在不修改操作数的情况下使用一连串的操作符重载?

class A 
{ 
public: 
    int a; 

    A(int b) 
    { 
     a = b; 
    } 
}; 

我想创建一个超载,使得我可以用它像这样

A a(1),b(2),c(3),&d; 
d = a + b + c; 

,而无需修改每个对象的内容。接下来顺理成章的事情将每次分配的内存新小盘这样的:

A &operator+ (const A &b) 
{ 
    A *c = new A(a+b.a); 
    return *c; 
} 

但是,这将创建一个新的问题:中间结果都将丢失,导致内存泄漏。 我可以很容易地解决这个问题,通过一个静态函数,需要三个对象引用,并将前两个的总和存储在第三个,但我敢打赌,必须有一些方法来使+过载发生我想要的方式。

所以问题是:有没有什么办法可以使用一个操作符重载链,它不会修改操作数而不会导致内存泄漏?

回答

9

你可以简单地通过值使用通和做到这一点:

A operator+ (A other) //pass by value 
{ 
    other.a += a; 
    return other; 
} 

或者,由于成员a是公开访问,则可以(而应该)使operator+非成员函数:

A operator+(A left, A const &right) 
{ 
    left.a += right.a; 
    return left; 
} 

注意,第一参数按值接受,和第二,参考文献。这样,你不需要在函数中声明一个局部变量。你可以使用第一个参数;毕竟它是本地的函数,你可以做任何你想要做的事情:在这种情况下,我们只需添加right.a并返回它。


类的更好的设计是这样的:(阅读评论)

class A 
{ 
    int a; //make it private 
public:  
    A(int b) : a(b) //use member initialization list 
    { 
    } 
    A& operator+=(A const & other) //add `+=` overload, as member of the class 
    { 
     a += other.a; 
     return *this; 
    } 
}; 

//and make `+` non-member and non-friend 
A operator+(A left, A const & right) 
{ 
    left += right; //compute this in terms of `+=` which is a member function 
    return left; 
} 
+1

+1以避免手动复制。 – Sven 2012-04-28 03:19:06

+0

抱歉,您的回答似乎忽略了一个事实,即我特意询问了一种不修改任何操作数对象 – 2012-04-28 03:21:23

+0

@ user803253的方法:我不修改*操作数*;操作数作为值传递,这意味着您在函数中修改的是操作数的*副本。无论如何,我发布了一个更好的设计,你应该采用。 – Nawaz 2012-04-28 03:25:39

4

operator+内部没有必要使用指针。您可以在堆栈分配的中间目标,然后返回它:

A operator+ (const A &b) 
{ 
    A c(a+b.a); 
    return c; 
} 

或者只是:

A operator+ (const A &b) 
{ 
    return A(a+b.a); 
} 

或者更简单:

​​

由于这个隐式调用A::A(int)

请注意,我从返回类型中删除了引用。您不能将非const引用返回给本地。

那么你会使用这种方式:

A a(1),b(2),c(3),d; 
d = a + b + c; 

注意d不再是一个参考。

+0

警示:您正在返回引用临时对象。这不是一个好主意! – 2012-04-28 03:15:41

+0

很棒!谢谢。我知道一些简单的事情需要完成。 – 2012-04-28 03:17:19

+0

只要我发布我的答案,我注意到OP是返回引用,但立即修复我的答案。 – mfontanini 2012-04-28 03:17:45

相关问题