Why does the following CPP code output yy1 instead of yx1? Why is the result different from directly adjusting z-> xx ()?

-sharpinclude <iostream>
using namespace std;
class a {
public:
    void virtual x() {
        cout << "x" << endl;
    }
    void xx() {
        cout << "x1" << endl;
    }
};

class b :public a {
public:
    void x() {
        cout << "y" << endl;
        xx();
    }
    void xx() {
        cout << "y1" << endl;
    }
};

int main()
{
    b b1;
    a* z = &b1;
    z->x();
}

has nothing to do with dynamic preferences. The problem here is only caused by name hiding.

because this is clearly specified in the standard document.

6.3.10

  1. The declaration of a member in a derived class (Clause 13) hides the declaration of a member of a base class of the same name;

it is important to note that name is only required here, but not signature , so let me take a look at this code,

.
using namespace std;
class a {
public:
    void virtual x() {
        cout << "x" << endl;
    }
    void xx() {
        cout << "x1" << endl;
    }
    void xx(int)
    {
        cout << "call: void xx(int))" << endl;
    }
};

class b :public a {
public:
    void x() {
        cout << "y" << endl;
        xx(1);
    }
    void xx() {
        cout << "y1" << endl;
    }
};

int main()
{
    b b1;
    a* z = &b1;
    z->x();
}
prog.cc:21:9: error: too many arguments to function call, expected 0, have 1; did you mean 'a::xx'?
        xx(1);
        ^~
        a::xx
prog.cc:11:10: note: 'a::xx' declared here
    void xx(int)
         ^
1 error generated.
1

clang tells us that we can't see the void xx (int) in a in b . What are you doing? Because of the above, there are several conditions at the same time:

  1. xx is name .
  2. xx also found
  3. in a and b .

so the result is hides the declaration .

OK, let's sit down and practice, because these two conditions have to be completed at the same time, that is, the transaction set. If we break the second condition and remove the xx function in b , what will happen to this hiding ? It will disappear theoretically, isn't it?

-sharpinclude <iostream>
using namespace std;
class a {
public:
    void virtual x() {
        cout << "x" << endl;
    }
    void xx() {
        cout << "x1" << endl;
    }
    void xx(int)
    {
        cout << "call: void xx(int))" << endl;
    }
};

class b :public a {
public:
    void x() {
        cout << "y" << endl;
        xx(1);
    }
};

int main()
{
    b b1;
    a* z = &b1;
    z->x();
}
y
call: void xx(int))

sure enough, it passed the check and made sure that it was sent out.


this is a question of dynamic binding. You can learn from Baidu

.

conditions for dynamic binding:
(1) Public inheritance
(2) call virtual function
(3) call virtual function through object pointer or object reference of base class

in your code, z is a base class pointer pointing to a subclass object, and the function called by z is a virtual function, so dynamic binding occurs. The x () function of b1 is called, and the xx () function is called in this function. This function has the same name as the xx () function in the base class, so the xx () function of the base class is hidden, so no matter whether the xx () function is a virtual function or not. The invocation is always b1's own.

use z to call the xx () function. Because the xx () function is not a virtual function and does not meet the condition of dynamic binding, dynamic binding does not occur, so the xx () function in the base class is called

.
Menu