RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 914228
Accepted
pepsicoca1
pepsicoca1
Asked:2020-12-02 02:58:02 +0000 UTC2020-12-02 02:58:02 +0000 UTC 2020-12-02 02:58:02 +0000 UTC

为什么将派生类指针转换为基类指针时不调用基类虚函数?

  • 772

有一个简单的测试程序:

// Example program
#include <iostream>
#include <string>

using namespace std;

class a1 {
public:
    void printid() { cout << endl << "this is a1 id"; }
};

class a2 : public a1 {
public:
    void printid() { cout << endl << "this is a2 id"; };
};

int main() {
    a1 aa1;
    a2 aa2;

    a1* aa1_ptr = &aa1;
    a2* aa2_ptr = &aa2;

    a1* aa1_ptr_derived = (a1*)aa2_ptr;

    aa1.printid();
    aa2.printid();

    aa1_ptr->printid();
    aa2_ptr->printid();

    aa1_ptr_derived->printid();

    return 0;
}

这个程序的输出是:

this is a1 id   
this is a2 id   
this is a1 id   
this is a2 id   
this is a1 id   

如果您将 printid() 函数设为虚拟,则结果会发生显着变化。
即,如果程序是:

// Example program
#include <iostream>
#include <string>

using namespace std;

class a1 {
public:
    virtual void printid() { cout << endl << "this is a1 id"; }
};

class a2 : public a1 {
public:
    virtual void printid() { cout << endl << "this is a2 id"; };
};

int main() {
    a1 aa1;
    a2 aa2;

    a1* aa1_ptr = &aa1;
    a2* aa2_ptr = &aa2;

    a1* aa1_ptr_derived = (a1*)aa2_ptr;

    aa1.printid();
    aa2.printid();

    aa1_ptr->printid();
    aa2_ptr->printid();

    aa1_ptr_derived->printid();

    return 0;
}

这个程序的输出是:

this is a1 id   
this is a2 id   
this is a1 id   
this is a2 id   
this is a2 id   

也就是说,当我尝试从通过将派生指针转换为基类获得的基类指针调用虚函数时,将调用派生类虚函数。

问题:

  1. 这样对吗?毕竟,当我在基类指针上调用 printid() 时,我得到“这是 a1 id”。而当我从同一个指向基类的指针调用 printid(),但通过从派生类强制转换获得时,由于某种原因,“这是 a2 id”被调用了吗?

UPD1:

对不起,同事们,我彻底钝化了。我不会删除问题,让它挂在学生的恐惧。只是通常在设计时,我从下往上查看层次结构,并希望获得指向基类的指针的多态行为。他确实明白了。然后出于某种原因,我从上到下查看了层次结构,并出于某种原因决定在降低层次结构时,我应该接收基类的所有属性。

c++
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    AnT stands with Russia
    2020-12-02T03:08:33Z2020-12-02T03:08:33Z

    您在第二种情况下看到的行为是虚函数的重点。这就是它们的设计目的。所以不清楚为什么你对观察到的行为感到惊讶。

    通过定义虚函数,调用中特定函数的选择是根据调用中使用的对象的动态类型进行的。因为 在通话中

    aa1_ptr_derived->printid();
    

    指针aa1_ptr_derived实际上指向一个类型的对象a2,然后从类中调用该函数a2。这就是多态的全部思想。

    形式上,在 C++ 语言中,只有一种方法可以“抑制”多态性:在调用中指定一个限定的方法名

    aa1_ptr_derived->a1::printid();
    

    (加上构造函数和析构函数中虚拟调用的特性)。

    • 1
  2. KoVadim
    2020-12-02T03:09:59Z2020-12-02T03:09:59Z

    这样对吗?

    是的,这就是它的本意。

    这是通过虚函数表实现的。调用虚函数时,通常通过表中的数字来调用。表的地址存储在对象内部。但是表绑定到一个类,而不是一个对象。

    编译器是做什么的?如果他知道这是一个常规函数,他会立即替换它的地址。如果他看到这是一个虚函数,那么他会根据对象的地址计算表的地址(通常只是 +4 或类似的值)。然后在收到的表地址中找到所需的虚函数按编号起作用,就会有它的地址。

    将指针转换为祖先并不会改变计算表地址的本质。其实我们有。

    PS 在很多情况下,编译器可以确定被调用的函数等等。并且不使用虚函数表。

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5