C++ c++;派生类中的重载方法

C++ c++;派生类中的重载方法,c++,operator-overloading,C++,Operator Overloading,我有以下问题: 假设基类A与方法: A& operator+(A& a) {...} 我还有一个派生类B,它重载(或者至少应该如此)这个方法: A& operator+(B& b) {...} 问题是如果我想打电话给这样的人: b+a(其中b是类型b,a是类型a)我得到一个编译错误。 (错误C2679:二进制“+”:未找到接受类型为“a”的右操作数的运算符(或没有可接受的转换)) 这不应该调用基类方法吗?(看起来它覆盖了方法..) 若否,原因为何?有没有办法解

我有以下问题:

假设基类A与方法:

A& operator+(A& a) {...}
我还有一个派生类B,它重载(或者至少应该如此)这个方法:

A& operator+(B& b) {...}
问题是如果我想打电话给这样的人: b+a(其中b是类型b,a是类型a)我得到一个编译错误。 (错误C2679:二进制“+”:未找到接受类型为“a”的右操作数的运算符(或没有可接受的转换))

这不应该调用基类方法吗?(看起来它覆盖了方法..) 若否,原因为何?有没有办法解决这个问题(不要告诉我用a&重载B中的方法)

对不起,我没有给出格式化文本中的示例,但我不知道如何格式化它

提前谢谢


PS Im使用Visual studio 2010 beta。

问题在于您正在定义成员操作符,因此当调用
b+a
时,它会导致
b.operator+(a)
,而这是不存在的

公认的做法是定义自由运算符,这些运算符本身将根据参数调用[虚拟]成员。 编辑:我所说的标准示例是为输出流调整类层次结构:

class base
{
public:

  virtual ~base();
  virtual void print( std::ostream& ) const;
};

std::ostream& operator<<( std::ostream& out, const base& b )
{
  b.print( out ); return out;
}

希望这能给你足够的时间重新思考你的设计:)

你会想到一些事情。首先,您通常希望使操作符+“虚拟”。然后,引用B的派生运算符+将由于协方差而成为重写,而不是隐藏基类实现,这就是这里发生的情况

也就是说,我怀疑(但不能肯定地说,如果不编译一个测试项目),这实际上会解决您的问题。这是因为二进制运算符的标准答案是使用静态方法,在类上接受两个参数。C++ STL广泛使用了这种技术,我不知道有什么理由试图将二进制运算符作为实例方法实现,不管是不是虚拟的。这太令人困惑了,没有真正的正面。

这个问题叫做隐藏——派生类中的成员函数隐藏基类中同名的函数。在这种情况下,您无法访问A::operator+(A&),因为它被B::operator+隐藏。解决这个问题的方法是定义B::operator+(A&),并可能让它调用基类函数


Edit:有一个函数详细介绍了这个问题,并提供了另一个可能的解决方案,即使用关键字的

不,它不会调用基类函数。类B有一个
操作符+
,它没有采用正确的参数,即故事结束

您可以将
运算符+
定义为自由函数,而不是在任何类中。如果需要访问私人数据,可能是朋友:

A operator+(const A &lhs, const A &rhs) { ... }
B operator+(const B &lhs, const B &rhs) { ... }
然后b+a将呼叫第一个操作员,a+b也将呼叫第一个操作员。b+b将呼叫第二个

或者,您可以通过将其放入类B中来“取消隐藏”基类实现:

using A::operator+;
不过,最好不要这样做。大多数运算符作为自由函数工作得更好,因为这样可以在两个操作数上进行自动转换。C++从不在成员函数调用的LHS上执行转换。
顺便说一句,操作符+几乎肯定应该按值返回,而不是按引用返回,因为一旦函数返回,自动(堆栈)变量就不再存在。因此,需要向调用方传递结果的副本,而不是对结果的引用。由于这个原因,运算符+和继承不是一个很好的组合,尽管只要调用方知道它们在做什么,它可能就可以工作。

你能更好地解释一下你的意思吗?编辑:好的,我知道了,但这对我没什么帮助,但我不会真正使用+的真正语义,所以没关系!更正:我认为正如尼古拉所说,它们实际上是作为自由方法实现的。例如,查看STL中流类的>运算符重载。第二个更正:忽略第一段。我忘了C++中的协方差只适用于返回类型。这是有道理的,即使我认为这不应该发生。我将按照您所说的做,并在派生类中重新定义它。谢谢斯也从不喜欢它,但这就是C++的好与坏的方式。这是语言中一个晦涩难懂的角落,最终会咬到每个人。编译器的编写者一定有很好的理由希望这样做。别担心,如果我不需要,我不会这么做的。(im返回对新分配对象的引用)。谢谢,但我必须使用类方法来实现我想要的。如果您要返回对新分配对象的引用,几乎可以肯定,编写函数比调用
操作符+
要好,因为您无法匹配操作符+的常用语义。使用您的代码,以下所有泄漏内存:
acc=A+b
a=a+b
A&d=A+b+b。重载运算符+应该“表现得像”加法,否则为什么重载?能否详细说明为什么必须使用成员函数?据我所知,C++中没有任何成员函数可以做的,自由函数不能,除了代码<>这个/<代码>的明显速写,而不是指定对象。我明白为什么需要操作符,我不明白为什么它们需要成为成员函数。如果您打算以某种方式实现垃圾收集器,那么您可以避免内存泄漏。@George。使自由函数成为类的朋友,并在同一头文件/源文件中声明/定义它。这不会破坏封装,因为操作符是类的公共接口的一部分。它的代码是否恰好在类定义的大括号内无关紧要,尽管实际上有一种语法可以做到这一点,如果它让您感觉更好;-)。如果您不能忍受使用friend,那么就编写一个调用公共“add”成员函数的免费操作符。然后,您将获得对称转换处理,这是无法从成员函数运算符获得的。
using A::operator+;