重载虚函数集的部分继承

Ste*_*mit 9 c++ inheritance virtual-functions overloading

我以为我理解了继承,虚函数和函数重载,但我有一个案例,其中有关于这些特性之间的相互作用的事情让我望而却步.

假设我有一个包含重载虚函数的简单基类,以及从中派生的第二个类:

class b {
 public:
    virtual int f() { return 1; }
    virtual int f(int) { return 2; }
};


class d : public b {
 public:
    virtual int f(int) { return 3; }
};
Run Code Online (Sandbox Code Playgroud)

请注意,派生类d仅覆盖其中一个重载的虚函数.

我可以实例化一个类的对象df(int)在其上调用,没问题:

d x;
std::cout << x.f(0) << std::endl;
Run Code Online (Sandbox Code Playgroud)

但是当我尝试调用0参数函数时:

std::cout << x.f() << std::endl;
Run Code Online (Sandbox Code Playgroud)

它失败!gcc说"没有匹配函数来调用'd :: f()';候选者是:virtual int d :: f(int)".clang说"函数调用的参数太少,预期为1,有0;你的意思是'b :: f'吗?" 即使d派生出来的b是0-argument f()方法,编译器也会忽略它,并试图调用d1-argument方法.

我可以通过重复派生类中的0参数函数的定义来解决这个问题:

class d : public b {
 public:
    virtual int f() { return 1; }
    virtual int f(int) { return 3; }
};
Run Code Online (Sandbox Code Playgroud)

或者,正如clang的错误消息所示,我可以使用一种愚蠢的消歧语法,我从来没有猜到它会起作用:

std::cout << x.b::f() << std::endl;
Run Code Online (Sandbox Code Playgroud)

但我的问题是,我打破了什么规则,试图强制执行/保护/捍卫的规则是什么?我以为我试图在这里做的就是我认为继承的那种东西.

Tar*_*ama 6

这称为名称隐藏.

在派生类中声明具有相同名称的函数时,将隐藏基础中具有相同名称的所有函数.

为了获得对它们的非限定访问权限,using请在派生类中添加一个声明:

class d : public b {
 public:
    using b::f;
    virtual int f(int) { return 3; }
};
Run Code Online (Sandbox Code Playgroud)

  • @OthmanBenchekroun [basic.scope.hiding]/1`名称可以通过嵌套声明性区域或派生类中相同名称的显式声明来隐藏. (3认同)