C++ 将派生对象作为基类引用参数传递

C++ 将派生对象作为基类引用参数传递,c++,dynamic-binding,C++,Dynamic Binding,此示例显示将派生类对象传递给以基类引用为参数的函数。派生类中的成员函数gint隐藏基类中的gfloat。我明白这一点,我的问题与此无关 class Base { public: virtual void g(float x) throw() { cout << "Base::g(float)\n"; } }; class Derived : public Base { public: virtual void g(in

此示例显示将派生类对象传递给以基类引用为参数的函数。派生类中的成员函数gint隐藏基类中的gfloat。我明白这一点,我的问题与此无关

class Base {
public:
    virtual void g(float x) throw()
    {
        cout << "Base::g(float)\n";
    }
};

class Derived : public Base {
public:        
    virtual void g(int x) throw() // Bad: Hides Base::g(float)
    {
        cout << "Derived::g(int)\n";
    }
};


void sampleTwo(Base& b, Derived& d)
{
    b.g(3.14f);
    d.g(3.14f); // Bad: Converts 3.14 to 3 and calls Derived::g(int)
}

int main()
{
    Derived d;
    sampleTwo(d, d);
    return 0;
}

我的问题是关于输出基::gfloat。由于sampleTwo中“b”引用的对象是派生对象,动态绑定不应该调用派生类的g方法将float转换为int吗?

动态调度调用最终重写器。由于派生::g隐藏而不是重写Base::g,因此派生中Base::g的最终重写器仍然是Base::g。

gfloat和gint是不同的函数成员。如果您想让派生类工作,就必须在两个类中都使用gfloat

g可以重载签出函数重载:

示例gfloat和gint位于同一类和单独函数中:

class Derived : public Base {
public:

    void g(float x) throw();
    void g(int x) throw();

};
gint和gfloat是两种完全不同的方法。派生::gint不重写Base::gfloat。这些方法是不相关的

由于“派生”不会覆盖gfloat,因此您对b.g3.14f的期望是没有根据的。正如预期的那样,b.g3.14f应该调用Base::gfloat


如果您在派生中重写gfloat,那么b.g3.14f确实会调用派生::gfloat。

在编写派生类的函数来重写基类的虚函数时,最好使用override关键字,假设编译器具有合理的C++11支持。这样,如果函数没有按预期重写,编译器会给您一个错误。我也很惊讶,但我最初的猜测是base::gfloat调用了两次,而不是派生::gint,因为这两种情况下的函数调用都与gfloat的签名匹配,这是一个不同的函数,gint这是两个不同的函数,您的代码不会进行任何重写,您应该使用派生中的Base::g来取消隐藏Base::gfloat。
class Derived : public Base {
public:

    void g(float x) throw();
    void g(int x) throw();

};