1

I have written the following code to understand c++'s virtual, override, hide, overload meaning. I expect fc->g() give me output Child:g(int):i = 20, but it gives me Child:g(int):i = 10. It seems the pointer fz call Child::g(int i) correctly by following links of vtbl(virtual table), but it fails to access the correct parameter value for int i. I am really confused. Can anyone help?

#include <stdio.h>
#include <string>
#include <iostream>
#include <complex>
using namespace std;
class Father
{
public:
    Father();
    ~Father();
    // f(int) and f(double) are overload
    virtual void f(int);
    virtual void f(double);

    virtual void g(int i = 10);

private:
};
void Father::f(int i)
{
    cout << "Father:f(int)" << endl;
}
void Father::f(double i)
{
    cout << "Father:f(double)" << endl;
}
void Father::g(int i)
{
    cout << "Father:g(int):i = " << i << endl;
}
Father::Father()
{
    cout << "new father" << endl;
}
Father::~Father()
{
    cout << "delete father" << endl;
}
class Child : public Father
{
public:
    Child();
    ~Child();
    // using Father::f; // ucomment this to see the 'hide' effect
    void f(complex<double> i);  // this->f() hides function Father::f(int), Father::f(double)
    virtual void g(int i = 20); // void g(int i = 20) override;

private:
};
void Child::f(complex<double> i)
{
    cout << "Child:f(complex<double>)" << endl;
}
void Child::g(int i)
{
    cout << "Child:g(int):i = " << i << endl;
}
Child::Child()
{
    cout << "new Child" << endl;
}
Child::~Child()
{
    cout << "delete Child" << endl;
}
int main()
{
    Father father;
    Child child;
    Father *fc = new Child;
    child.f(1); // hide father.f(int)
    father.f(1);
    child.f(0.1); // hide father.f(double)
    father.f(0.1);
    child.Father::f(1);
    child.Father::f(0.1);
    child.g();         // Child:g(int):i = 20, override father.g(int i=10)
    child.Father::g(); // Father:g(int):i = 10
    fc->g();           // Child:g(int):i = 10, why?

    // this is not saft, some resources in child will not be released
    // should declare virtual ~Father()
    delete fc;
    return 0;
}
  • Overriding a virtual function does not allow you to change the default value. `fc` is a pointer to `Father` and, in the call `fc->g()` the compiler cannot assume that `fc` points at a `Child` AND is able to do that call even if the compiler doesn't have visibility of the definition of `Child`. In a complex project, having the behaviour of `fc->g()` change depending on whether the compiler has visibility of the definition of `Child` or not would be a source of obscure changes of program behaviour. – Peter May 06 '21 at 11:39

0 Answers0