2017-08-03 38 views
1

说有两个类:Base和Derived。代码如下所示。 我的问题是,程序如何知道d.print()(在代码中用A标记)是打算拨打Derived::print()而不是Base::print()C++:涉及继承和“使用”时的方法重载

请注意,我特意加了using Base::print;来混淆编译器。这两个print()方法具有相同的签名(我是对吗?),并且由于using声明而不相互隐藏。

#include <iostream> 
using namespace std; 

class Base { 
public: 
    void print() { cout << "print() of Base is called\n"; } 
}; 

class Derived : public Base { 
public: 
    void print() { cout << "print() of Derived is called\n"; } 
    using Base::print; // I delibarately added this line 
}; 

int main() { 
    Derived d; 
    d.print(); // A 

    Base *pBase = (Base *)&d; 
    pBase->print(); // B 
} 

结果是

print() of Derived is called 
print() of Base is called 

编辑:接受的答案给了报价。为了方便读者查阅我贴的(几乎)所有引用这里的段落,拆分句子:

使用声明引入了一个基类到派生类定义的成员,如暴露基地的保护成员作为派生的公共成员(这是我的预期)

如果名称是基类的重载成员函数的名称,则会引入具有该名称的所有基类成员函数。 (这也是我的预期)

如果派生类已经有一个成员具有相同的名称,参数列表和资格,派生类成员隐藏或覆盖(不冲突)引入的成员来自基类。 (解决我的问题)

+0

好吧,也许它不是超载..?但这不是这个问题的重点。提前致谢。 – user8385554

+0

你真的很惊讶吗? '使用Base :: print;'intorduces **所有重载**(可能有多个)。如果因为这个原因导致你们班上的冲突,那将是非常令人痛心的。 – StoryTeller

+0

@StoryTeller这让我感到困惑,因为我认为'using'声明应该重写名称隐藏机制(比如“覆盖override”),所以编译器应该会感到困惑。但显然这个覆盖再次被重写 - 毕竟,Derived :: print()覆盖了'Base :: print()'。 – user8385554

回答

4

的明确介绍using不躲,因为这条规则(从cppreference documentation for using

你在派生类中有方法如果派生类已经与成员相同的名称,参数列表和资格,派生类成员隐藏或覆盖(不冲突)从基类引入的成员。

编译器不会混淆,它正在做正确的事情。 using未在派生类中隐藏print()方法,因为它定义了print()方法。

当你调用print()一个Base指针,print()不虚基指针只能调用与静态类型的它指向的东西注册的方法,即Base::print()

+0

感谢您指出此网页!我完全错过了这一个。 – user8385554

+0

@ user8385554我先回答'A',然后回答'B',哪一部分让你感到困惑? – Curious

+1

对不起,我只是承诺你的意思,所以我只是修改了我的评论.. – user8385554