下面这个C++代码为什么输出y y1而不是y x1呢?为什么和直接调z->xx()的结果不同?

发布于 2022-09-07 04:21:38 字数 458 浏览 27 评论 0

#include <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();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寂寞花火° 2022-09-14 04:21:38

和"動態邊編"無關. 這裏的問題只是name hiding導致的罷了.

因爲這是在標準文檔中有着明確規定的.

§ 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;

需要注意的是這裏只要求的name, 不要求signature, 那麼讓我們來看這份代碼,

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告訴我們在b中是看不到a中的void xx(int). 爲什麼呢? 就是因爲上面所說的, 同時滿足了兩個條件:

  1. xx是name.
  2. xx同時在ab中出現

所以結果就是hides the declaration.

好, 我們來坐下實驗, 因爲這兩個條件要同時滿足, 即成交集, 如果我們破壞了第二個條件, 把b中的xx函數移除, 那麼這個hiding會怎麼樣呢? 理論上就會消失, 到底是不是呢?

#include <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))

果然通過編譯並且正確輸出了.

心清如水 2022-09-14 04:21:38

这是属于动态联编的问题,可以百度学习一下

实现动态联编的条件:
(1)公有继承
(2)调用虚函数
(3)通过基类的对象指针或者对象的引用调用虚函数

在你的代码中z是一个基类指针,指向了一个子类对象,并且z调用的函数x()是一个虚函数,所以发生了动态联编,调用的是b1的x()函数,在这个函数中又调用了xx()函数,此函数与基类中的xx()函数重名,所以基类的xx()函数被隐藏了,所以不论xx()函数是否为虚函数,调用的始终是b1自己的。

使用z去调用xx()函数,由于xx()函数不是虚函数,不满足动态联编的条件,所以不发生动态联编,因而调用的是基类中的xx()函数

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文