c++派生类中的重载方法
我有以下问题:
假设基类 A 具有方法:
A& operator+(A& a) {...}
我还有一个派生类 B,它重载(或至少应该如此)此方法:
A& operator+(B& b) {...}
问题是,如果我想调用类似的方法: b + a(其中b是B类型,a是A类型)我得到一个编译错误。 (错误 C2679:二进制“+”:找不到采用“A”类型右侧操作数的运算符(或者没有可接受的转换))。
那不应该调用基类方法吗? (看起来它覆盖了该方法..) 如果没有,为什么?有没有办法解决这个问题(不要告诉我用 A& 重载 B 中的方法)
抱歉,我没有在格式化文本中给出示例,但我不知道如何格式化它。
提前致谢!
PS 我使用 Visual studio 2010 beta。
I have the following question:
Assume base class A with method:
A& operator+(A& a) {...}
I also have a derived class B which overloads (or at least it should so) this method:
A& operator+(B& b) {...}
The problem is that if i want to call something like:
b + a (where b is of type B and a of type A) i get a compile error.
(error C2679: binary '+' : no operator found which takes a right-hand operand of type 'A' (or there is no acceptable conversion)).
Shouldnt that call the base class method? (it looks like it overrides the method..)
If not, why? Is there a way to fix this (dont tell me to overload the method in B with A&)
Sorry i dont give examples in formated text, but i dont know how to format it.
Thanks in advance!
PS Im using Visual studio 2010 beta.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不,它不会调用基类函数。 B 类有一个
operator+
,它没有采用正确的参数,故事结束了。您可以将
operator+
定义为自由函数,而不是在任何类中。也许朋友,如果需要访问私有数据:那么 b + a 将调用第一个运算符,a + b 也会调用。 b + b 将调用第二个。
或者,您可以通过将其放入类 B 中来“取消隐藏”基类实现:
不过,最好不要这样做。大多数运算符作为自由函数可以更好地工作,因为这样您就可以在两个操作数上进行自动转换。 C++ 从不对成员函数调用的 LHS 执行转换。
顺便说一句,operator+ 几乎肯定应该按值返回,而不是按引用返回,因为一旦函数返回,自动(堆栈)变量就不再存在。因此,调用者需要传递结果的副本,而不是对其的引用。因此,operator+ 和继承并不是一个很好的组合,尽管只要调用者知道他们在做什么,它就可能起作用。
No, it won't call the base class function. Class B has an
operator+
, it doesn't take the correct parameter, end of story.You can define
operator+
as a free function, not in any class. Perhaps a friend, if it needs to access private data:Then b + a will call the first operator, as will a + b. b + b will call the second.
Alternatively, you could "un-hide" the base class implementation, by putting this in class B:
it's probably best not to, though. Most operators work better as free functions, because then you get automatic conversions on both operands. C++ never performs conversions on the LHS of a member function call.
Btw, operator+ almost certainly should return by value, not by reference, since an automatic (stack) variable no longer exists once the function returns. So the caller needs to be passed a copy of the result, not a reference to it. For this reason operator+ and inheritance aren't a great mix, although it can probably work as long as the caller knows what they're doing.
这个问题被称为“隐藏”——派生类中的成员函数隐藏了基类中同名的函数。在这种情况下,您无法访问 A::operator+(A&),因为它被 B::operator+ 隐藏。解决这个问题的方法是定义 B::operator+(A&),并可能让它调用基类函数。
编辑:有一个部分在 C++ FAQ Lite 中,它更详细地介绍了这个问题,并提供了另一种可能的解决方案,即
using
关键字。The problem is called hiding - a member function in a derived class hides functions with the same name in the base class. In this case you can't access A::operator+(A&) because it's being hidden by B::operator+. The way to fix this is to define B::operator+(A&), and possibly have it call the base class function.
Edit: There's a section in the C++ FAQ Lite that goes into more detail about this problem and offers another possible solution, namely the
using
keyword.问题是您正在定义 member 运算符,因此当调用
b + a
时,会产生b.operator+( a )
,其中不存在。可接受的做法是定义自由运算符,它们本身将调用参数上的[虚拟]成员。
编辑:
Standard example of what I'm talking about is adapting a class hierarchy for output streaming:
这对于数学运算实际上不起作用,因为您希望按 [const] 值返回,而不是引用,即避免像
a + b = c;
这样的废话。例如,定义了实数和复数的加法,但结果会产生复数,因此您无法从
real
派生出complex
。另一种方式——也许吧。但您仍然想定义精确的操作接口:希望这足以让您重新思考您的设计:)
The problem is that you are defining the member operator, so when called as
b + a
it results inb.operator+( a )
, which doesn't exist.Accepted practice is to define free operators that themselves would call [virtual] members on the arguments.
Edit:
Standard example of what I'm talking about is adapting a class hierarchy for output streaming:
This doesn't really work for math operations since you want to return by [const] value, not reference, i.e. avoid nonsense like
a + b = c;
.For example, addition of real and complex numbers is defined, but yields complex number as the result, so you cannot derive
complex
fromreal
. The other way - maybe. But still you want to define exact operations interface:Hope this gives you enough to re-think your design :)
我想到了几件事。首先,您通常希望将运算符 + 设为“虚拟”。然后,派生运算符 + 引用 B 将由于协方差而被覆盖,而不是隐藏基类实现,这就是这里发生的情况。
也就是说,我怀疑(但在不编译测试项目的情况下不能肯定地说)这实际上可以解决您的问题。这是因为二元运算符的标准答案是使用在类上采用两个参数的静态方法。 C++ STL 广泛使用这种技术,而且我不知道尝试将二元运算符实现为实例方法(无论是否为虚拟方法)的原因。这太令人困惑了,没有真正的好处。
Couple of things come to mind. First, you would generally want to make the operator + "virtual". Then, the derived operator + taking a reference to B would be an override due to co-variance, instead of hiding the base class implementation, which is what is happening here.
That said, I suspect (but can't say for certain without compiling a test project) that that would actually solve your problem. That's because the standard answer for binary operators is to use static methods that take two parameters on the class. The C++ STL uses this technique extensively, and I don't know of a reason to attempt to implement binary operators as instance methods, virtual or not. It's just too confusing, with no real up-side.