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;
  // ....
}