繁体   English   中英

从派生类访问虚拟基类函数

[英]Accessing virtual base class function from a derived class

1.在下面的主要函数中,为什么d.foo(9.5)没有从基类中选择Base::foo(double)方法? 派生类不继承该方法吗?

2.什么原因导致编译错误?

class Base {
public:
    virtual void foo(int){
        cout << "Base::foo(int)" << endl;
    }
    virtual void foo(double){
        cout << "Base::foo(double)" << endl;
    }
};

class Derived : public Base {
public:
    virtual void foo(int){
        cout << "Derived::foo(int)" << endl;
    }
};

void main() {
    Derived d;
    Base b, *pb = &d;

    d.foo(9);     // selects Derived::foo(int)         
    d.foo(9.5);   // selects Derived::foo(int)         
    pb->foo(9);   // selects Derived::foo(int) 
    pb->foo(9.5); // selects Base::foo(double)  

    Derived * d; 
    d->foo(9);    // compile error
}

在下面的主要函数中,为什么d.foo(9.5)没有从基类中选择Base::foo(double)方法? 派生类不继承该方法吗?

是的,但是在派生类中,具有相同名称的函数将其隐藏了。 您可以在派生类中使用using-声明取消隐藏它:

using Base::foo;

是什么导致编译错误?

您正在尝试声明另一个名为d变量。 将名称更改为尚未使用的名称; 并将其初始化为指向有效对象,否则您将遇到运行时错误或其他未定义的行为。

Derived * pd = &d; 
pd->foo(9);    // selects Derived::foo(int) 

另外, main的返回类型错误。 它必须返回int

1)因为这正是多态性的工作方式。 如果在派生类中重新定义了虚函数,则将调用此(仅此)重新定义的版本。 如果该函数不是virtual函数,反之亦然:只会调用基类函数。

//Example 1: non-virtual function
class Base
{
public:
    void foo()
    {
        std::cout << "Base";
    }
}

class Derived : public Base
{
public:
    void foo()
    {
        std::cout << "Derived";
    }
}

Base * base = new Base();
base->foo()//prints "Base"
Base * derived = new Derived();
derived->foo()//prints "Base", since the function is not virtual, and the version from the base class is called


//Example 2: virtual function
class Base
{
public:
    virtual void foo()
    {
        std::cout << "Base";
    }
}

class Derived : public Base
{
public:
    void foo()
    {
        std::cout << "Derived";
    }
}

Base * base = new Base();
base->foo()//prints "Base"
Base * derived = new Derived();
derived->foo()//prints "Derived", since the function is virtual, and the redefined version from Derived class is called

2)发生编译错误是因为您有一个冲突的声明-两个对象称为d

编译错误是由于main()中两个具有相同名称的变量引起的。

关于您的问题,继承的函数没有为您的Derived实例调用(除非通过指向Base指针)

该标准描述了“隐藏规则”,这使之成为现实。 本质上,在派生类中声明的成员函数会隐藏具有相同名称但从基类继承的签名不同的继承函数。 隐藏规则与继承的函数是否为虚拟函数无关。

常见的解决方案是using Base::foo引入基类的所有继承函数。 例如,

class Base {
public:
    virtual void foo(int){
        cout << "Base::foo(int)" << endl;
    }
    virtual void foo(double){
        cout << "Base::foo(double)" << endl;
    }
};

class Derived : public Base {
public:
    using Base::foo;
    virtual void foo(int){
        cout << "Derived::foo(int)" << endl;
    }
};

另一个解决方案是记住显式重写该函数的所有继承版本(实现派生类版本以仅调用每个函数的基类版本)。 这适用于不支持如上所述的using指令的较早的编译器。 要注意的是,必须对每个继承的重载都明确地执行此操作,并且很容易错过其中一个。

  Derived * d; 
  d->foo(9);    // compile error

您尚未实例化该对象:

派生* d =新派生;

如果未创建对象,则编译器将使用先前的d声明:不是指针的派生d。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM