C ++虚拟函数:调用基类函数而不是派生

时间:2018-08-01 15:58:38

标签: c++11 c++-cli

我有以下代码段:

using namespace std;
class base
{
    public:
    virtual void print(char a){ std::cout<<" Base "<<std::endl;}
};
class derived :public base
{
    public:
    void print(floata)  {std::cout<<" Derived "<<std::endl;}
};

int main()
{
    base* d = new derived;
    d->print(1.5);

    return 0;
}

输出为“基本” 为什么输出来自基本函数而不是衍生函数

2 个答案:

答案 0 :(得分:1)

您尚未覆盖该基类中的函数,您已重载:该派生类中的版本以float作为参数,与使用char的基类方法完全不同。此外,派生类中的float版本阴影基类版本:派生类型上的调用无法访问基类版本。

因此,以下代码

Derived d;
d.print('a');
d.print(1.5);

将打印

Derived
Derived

因为编译器将调用解析为print()中唯一的Derived版本。

同样,当您通过指向d->print(1.5)的指针调用Base时,调用将无法访问派生类的版本:编译器查看基类,发现没有{{1 }}方法使用print()参数定义,并将其转换为float。然后,它将调用char的唯一实现,该实现恰好由基类提供。


如果仅更改派生类中的print(char)方法的签名以匹配基类的签名,则奇怪的行为将消失。

答案 1 :(得分:0)

声明Base* d = new Derived;时,类的类型为Base,由typeid(d).name()打印,因此该实例无权访问子类方法。如果将类型更改为“派生”,则将调用子方法:

#include <iostream>
#include <typeinfo>

class Base
{
  public:
    virtual void print(char a) {
        std::cout << " Base " << std::endl;
    }
};

class Derived : public Base
{
  public:
    void print(float a) {
        std::cout << " Derived " << std::endl;
    }
};

int main()
{
    Derived* d = new Derived;
    std::cout << "class type is: " << typeid(d).name() << std::endl;
    d->print(1.5);

    return 0;
}

输出:

class type is: P7Derived
 Derived 

此外,声明父类print方法virtual不允许Base实例调用print的子版本,因为子版本尚未覆盖它(不同的标头) )。使用Base *d = new Derived;创建Base实例,并将Derived类中的Derived print方法标头更改为void print(char a),将允许您调用子print方法并输出{{1 }},甚至可以使用Derived关键字从Base实例中获取。

virtual

输出:

#include <iostream>
#include <typeinfo>

class Base
{
  public:
    virtual void print(char a) {
        std::cout << " Base " << std::endl;
    }
};

class Derived : public Base
{
  public:
    void print(char a) {
        std::cout << " Derived " << std::endl;
    }
};

int main()
{
    Base* d = new Derived;
    std::cout << "class type is: " << typeid(d).name() << std::endl;
        d->print(1.5);

    return 0;
}

希望这有助于了解情况-我建议在此repl中使用不同的实例和标头来查看它们的作用。