c++ - 为什么基类函数没有被同名的派生类函数隐藏

标签 c++ inheritance

我目前正试图理解隐藏在 C++ 继承中的名称。

我在 C++ primer plus 上读过这个,第 744 页

In short, redefining inherited methods is not a variation of overloading. If you redefine a function in a derived class, it doesn't just override the base class declaration with same function signature. Instead, it hides all base class methods of the same name, regardless of the argument signatures.

所以我尝试了,这是我的两个类,Base 和 Derived

class Base{
public:
    Base(){
        cout << "Base::Base() called\n";
    }

    virtual ~Base(){}

    virtual void output(int x){
        cout << "Base::output(int x) called\n";
    }

    virtual void output(double x){
        cout << "Base::output(double x) called\n";
    }

    virtual void output(char x){
        cout << "Base::output(char x) called\n";
    }

    virtual void output(string x){
        cout << "Base::ouput(string x) called\n";
    }
};


class Derived : public Base{
public:
    Derived():Base(){
        cout << "Derived::Derived() called\n";
    }

    virtual ~Derived(){}

    virtual void output(string x){
        cout << "Derived::ouput(string x) called\n";
    }

};

根据本书,void Base::output(string x)将被重新定义,所有其他同名成员函数将被隐藏。

但是下面两段代码讲的是不同的故事。

Derived* x = new Derived();
x->output(7);

这段代码无法按预期编译,错误信息是

No viable conversion from 'int' to 'string'

但如果我这样做,

Base* x = new Derived();
x->output(7);

它神奇地起作用了,并给出了以下输出:

Base::Base() called
Derived::Derived() called
Base::output(int x) called

为什么会发生这种情况,指针类型真的会影响查找吗? 顺便说一句,这是在 Xcode 上。

最佳答案

对于这段代码:

Derived* x = new Derived();
x->output(7);

编译器将首先尝试解析该函数​​,它发现 Derived 有一个名为 output 的函数。一旦找到它,编译器就不会再查找了。然后它将解析参数并发现参数不正确并失败。

后期绑定(bind)的任何一种方式都不适用于此处,因为您正在使用派生类指针访问基类中的函数。你将不得不向上转型。

对于这段代码:

Base* x = new Derived();
x->output(7);

编译器认为 x 是 Base 类型,它具有带 int 参数的函数。编译器解析函数并设置。如果您要覆盖多态行为的函数,这将是合适的用法。

请注意,您可以调用 x->output("yes");并且将调用正确的函数;这将是派生版本。这是使用 vtable 的地方。

对于编译器为什么会这样做的原因,研究了“脆弱的基类问题”。

关于c++ - 为什么基类函数没有被同名的派生类函数隐藏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36682609/

相关文章:

c++ - 为什么我需要三个嵌套大括号来调用对二维数组进行常量引用的赋值运算符?

c++ - 如何计算给定 IPv4 网络掩码的前缀长度?

c++ - 如何在 C++ 中强制使用奇怪的重复模板模式

php - 继承困惑。添加一个特殊的类,使错误在表单验证时变得明显

c++ - 调用虚函数时的静态成员函数语义

c++ - 函数成员中的 enable_if 用于 void 和继承

c++ - 错误 C2440 : 'initializing' : cannot convert from 'classname *' to 'classname'

c++ - if 条件所需的逻辑帮助

C++函数的继承,传入参数

javascript - react 图标点击事件