虚函数(C++ 继承)[关闭]

问题描述 投票:0回答:1

假设我们有以下代码:

#include <iostream>
#include <string>
using namespace std;
class A {
public:
    A() : m_name("A Name") {}
    virtual void printName() { cout << m_name << "\n"; }
private:
    string m_name;
};

class B : public A {
public:
    B() : b_m_name("B Name") {}
    void printName() { cout << b_m_name << "\n"; }
private:
    string b_m_name;
};

int main() {

    A* ONE = new B;
    B* TWO = new B;

    ONE->printName();
    TWO->printName();

    return 0;
}

编辑:我的问题不是“输出是什么”;我知道我可以在 visual studio 中运行它并得到答案。我的问题更多是关于“为什么输出是这样的?”

我猜它会先输出“A Name”,然后再输出“B name”。我对此的一些推理尝试是 ONE 是类型 A 的指针,因此指向新 B 对象的一部分,即 A 对象。因此,当我们调用 ONE.printName();它调用类 A 的 printName(),反之亦然。

我不确定我的推理(甚至我的回答)是否正确。这有点令人困惑,因为我知道编译器可以有效地在 A* 和 B* 类型的指针之间进行转换,所以它们是一回事…… 这特别让我感到困惑,因为如果我的上述推理是正确的(ONE 是 A 类型的指针,因此指向新 B 的 A 部分),那么不能说它同时指向新 B 和A 在 B 中,因为它们实际上位于同一地址?如果是这样,为什么编译器不同时调用 A 和 B 的 printName() 函数? 区别是否仅在于我们宣布 ONE 为 A* 而不是 B*?

任何澄清将不胜感激。

c++ inheritance polymorphism virtual-functions
1个回答
0
投票

我的猜测是它会先输出“A Name”,然后再输出“B name”。我对此的一些推理尝试是 ONE 是一个指针 属于 A 类型,因此指向新 B 对象的 A 部分 目的。因此,当我们调用 ONE.printName();它称为A类 printName(),反之亦然。

根据用于调用虚函数的指针的动态类型调用虚函数。

来自 C++ 17 标准(3 个术语和定义)

3.9

动感型

最派生对象(4.5)的类型,其 glvalue 引用 [示例:如果指针 (11.3.1) p 的静态类型为“pointer 到 B 类”指向 D 类的对象,派生自 B (第 13 条),表达式 *p 的动态类型是“D”。参考 (11.3.2) 的处理方式类似。 - 结束示例]

你声明了两个指向分配对象的指针

class B

A* ONE = new B;
B* TWO = new B;

指针

ONE
的静态类型是
A *
,动态类型是
B *
。 所以对于这个说法

ONE->printName();

函数

printName
在类
A
中搜索。因为它是一个虚函数并且指针的动态类型是
B *
然后在指针指向的类型
B
的对象中的虚函数指针表中搜索指向该函数的指针
ONE
, 所以类中定义的函数
B
被调用了

在这份声明中

TWO->printName();

因为指针

TWO
的静态类型是
B *
然后在类
B
中搜索函数。由于指针的动态类型也是
B *
然后调用类
B
中定义的函数。

在这两个语句中调用了类

B
中定义的相同函数。

所以两个语句输出

B Name

就是虚函数的概念。

© www.soinside.com 2019 - 2024. All rights reserved.