C++ 如果派生类重写了基类方法,为什么要调用基类方法?
考虑以下计划:C++ 如果派生类重写了基类方法,为什么要调用基类方法?,c++,inheritance,C++,Inheritance,考虑以下计划: class Base { public: virtual void foo() const { cout << "Base::foo()" << endl; } }; class Derived : public Base { public: virtual void foo() { cout << "Derived::foo()" << endl; } }; vo
class Base {
public:
virtual void foo() const {
cout << "Base::foo()" << endl;
}
};
class Derived : public Base {
public:
virtual void foo() {
cout << "Derived::foo()" << endl;
}
};
void func(Base& obj) {
obj.foo();
}
void main() {
Derived d;
func(d); // Base::foo() is printed
}
类基{
公众:
虚拟void foo()常量{
cout您没有重写该方法,因为Derived::foo
并不完全相同
要重写方法,基版本和重写版本必须相同,包括const
-ness.在派生类中,函数签名如下:
virtual void foo(); //Derived::foo
它没有提到const
。它是一个非const成员函数,而Base::foo
是一个const成员函数。它们是两个不同的函数,因为const
是函数签名的一部分
virtual void foo() const; //Base::foo
派生类不重写此函数,而是添加另一个函数
所以解决办法是:
class Derived : public Base {
public:
virtual void foo() const {
cout << "Derived::foo()" << endl;
}
};
但是,如果将上述代码更改为以下代码:
void func(Derived & obj) {
obj.foo(); //calls Derived:foo
}
现在将选择非常量版本,因为Base::foo
隐藏在Derived
类中
由于Derived::foo
隐藏了Base::foo
,因此不能使用Derived
的实例调用后者
现在,让我们取消隐藏Base::foo
,并做更多的实验
class Derived : public Base {
public:
using Base::foo; //<----------------this unhides Base::foo
virtual void foo() {
cout << "Derived::foo()" << endl;
}
};
第一个将调用非常量版本的Derived::foo
,第二个将调用常量版本的Base::foo
。原因很简单,对于常量对象,只能调用常量函数,但对于非常量对象,两者都可以调用,但如果非常量版本可用,则会选择非常量版本
请参阅在线演示:您所做的是所谓的“重载”。正如@SLaks所指出的,在重写时,签名需要相同。const
是签名的一部分。void foo()const
是与void foo()不同的函数。你根本就不重写。这就是为什么。< P> C++中,你可以有两个函数,名字和参数相同,唯一的区别是代码> const < /C> >而不是。
其思想是,有时您需要不同的行为。例如,访问函数可能具有不同的返回类型:
class MyClass
{
public:
virtual Xxx * GetXxx();
virtual Xxx const * GetXxx() const;
// ....
}
您可以单独重写这些函数
在您的例子中,当您从一个非常量对象调用foo
时,您调用了函数的非常量变量。由于您已经重写了常量变量,基类中的变量就是被调用的变量。1)不重写2)是的,如果签名不同,它就不是重写!请注意,它不必完全相同;如果重写的回合类型可能和被重写函数的返回类型是协变的。@詹姆斯:参数类型也可能是反变的。它也不是真正的重载,而是隐藏的。所以为什么选择常量版本而不是非常量?有什么规则吗?或者它恰好是第一个选项?当然,愚蠢的我:(谢谢。有时候你已经习惯了复杂的情况,以至于忘记了最基本的:)
void f(Derived& obj) {
obj.foo(); //Which function? Base::foo or Derived::foo?
}
void g(const Derived & obj) {
obj.foo(); //Which function? Base::foo or Derived::foo?
}
class MyClass
{
public:
virtual Xxx * GetXxx();
virtual Xxx const * GetXxx() const;
// ....
}