根据下面的代码,不应该打印Calling B
,而不是Calling A
?不是a
a B
的运行时类型,因此虚拟调用应该导致对B::operator=
的调用(因为虚拟调用由左操作数确定)?
#include <iostream>
class A
{
public:
virtual A& operator=(const A& a_) { std::cout << "Calling A" << std::endl; }
};
class B : public A
{
public:
virtual B& operator=(const B& b_) { std::cout << "Calling B" << std::endl; }
};
int main() {
B b1;
B b2;
A& a = b1;
a = b2; // Prints "Calling A", should be "Calling B"?
return 0;
}
答案 0 :(得分:3)
a = b2;
不虚拟来电。
原因是B::operator=(const B&)
没有覆盖A::operator=(const A&)
,因为他们的签名不同。
您可以使用override
让编译器自动为您检查这些内容。
使用override
会做两件事:
答案 1 :(得分:2)
此方法:
mouseMove
不会覆盖此方法:
virtual B& operator=(const B& b_)
为了覆盖基类的方法,子进程必须具有相同的方法签名。
调用virtual A& operator=(const A& a_)
不会将实现推迟到派生类,因为派生类没有A::operator=
的实现。
答案 2 :(得分:0)
a
是class A
的对象,原因a = b2
会调用A& operator=(const A& a_)
,b2
的类型将转换为A
类型。测试b1 = b2
将输出“呼叫B”。
operator=
覆盖对于每个类都是唯一的。没有必要将它声明为虚函数。
答案 3 :(得分:0)
首先,正如其他人已经说过的那样,你的覆盖并不是 - 它只是一个过载。使用override关键字来确认这一点。
解决方案是为派生类运算符提供与基类1完全相同的签名,将A和dynamic_cast转换为正文中的B.
如果调用者尝试将A分配给B(即,转换失败),您需要考虑该怎么做。正如Alf在评论中提到的,这就是虚拟作业不受欢迎的原因。
答案 4 :(得分:-1)
它只会调用A :: operator =。 。由于c ++中的名称隐藏功能,它是方法重载方案,你无法在两个不同的类中实现(即使它是继承的)。