我了解虚函数和运行时调用的基本概念。但我试过了 运行一些困扰我的代码
class A {
public:
A& operator=(char) {
cout << "A& A::operator=(char)" << endl;
return *this;
}
virtual A& operator=(const A&) {
cout << "A& A::operator=(const A&)" << endl;
return *this;
}
};
class B : public A {
public:
B& operator=(char) {
cout << "B& B::operator=(char)" << endl;
return *this;
}
virtual B& operator=(const B&) {
cout << "B& B::operator=(const B&)" << endl;
return *this;
}
};
int main() {
B b1;
B b2;
A* ap1 = &b1;
A* ap2 = &b1;
*ap1 = 'z';
*ap2 = b2;
}
运行此程序会给我以下输出: -
A& A::operator=(char) //expected output
A& A::operator=(const A&) //Why this Output? in case of *ap2 = b2;
b2
是B
类型的对象,但仍然是虚拟A& operator=(const A&)
而不是虚拟B& operator=(const B&)
。为什么会这样?
答案 0 :(得分:3)
因为virtual B& operator=(const B&)
未覆盖virtual A& operator=(const A&)
;论点不同。
答案 1 :(得分:2)
对于要覆盖基类函数的派生类函数,派生类函数需要具有完全相同的函数原型(例外:允许使用协变返回类型)。
派生类=
中的B
运算符在基类=
中没有与A
相同的函数原型,因此它不会覆盖基类{ {1}}。
唯一可用的=
运算符是被调用的运算符。
答案 2 :(得分:2)
对于要被视为覆盖的函数,签名必须与基类中的版本完全匹配(好吧,如果返回指针或引用,则返回类型可能是协变的)。也就是说,您需要定义
B& B::operator= (A const&)
从基类覆盖版本。请注意,对于覆盖函数中的输入参数,协变是没有意义的,因为您无法保证仅使用基类在上下文中使用派生对象调用基类版本。如果覆盖函数的任何参数都可能是逆变的,但C ++不支持这一点。
答案 3 :(得分:2)
这里在派生类中,函数采用B而在基类中采用A.因此,基本上它不会被覆盖,因为函数参数是不同的。
另请注意,在覆盖的情况下,返回类型可能会有所不同,因为在您的情况下,您将返回基础中的A的引用和派生中的B的引用。 虚拟基地&amp; func(const Base&amp;) 虚拟衍生&amp; func(const Base&amp;) 这是覆盖
的有效形式