C++ 虚函数表现怪异

标签 c++ inheritance virtual-functions

我正在尝试理解虚函数和虚继承。在大多数情况下,我认为我成功地掌握了它以及它与多态性的关系,我一直在阅读 vptr 如何与派生对象一起工作等等,但是下面的例子让我失望了,它是我在算法和C++ 书中的数据结构:

#include <iostream>
using namespace std;

class Class1 {
public:
    virtual void f() {
        cout << "Function f() in Class1\n";
    }

    void g() {
        cout << "Function g() in Class1\n";
    }
};

class Class2 {
public:
    virtual void f() {
        cout << "Function f() in Class2\n";
    }

    void g() {
        cout << "Function g() in Class2\n";
    }
};

class Class3 {
public:
    virtual void h() {
        cout << "Function h() in Class3\n";
    }
};

int main() {
    Class1 object1, *p;
    Class2 object2;
    Class3 object3;

    p = &object1;
    p->f();
    p->g();

    p = (Class1*) &object2;
    p->f();
    p->g();

    p = (Class1*) &object3;
    p->f(); // possibly abnormal program termination;
    p->g();
    // p->h(); // h() is not a member of Class1;
    return 0;
}

输出:

Function f() in Class1
Function g() in Class1
Function f() in Class2
Function g() in Class1
Function h() in Class3
Function g() in Class1

除了最后一句我都懂p->f(); .作为序言,我知道我们不能直接调用 h()来自 p因为类型转换成Class1类型,但不应该是 Class3 vptr 只指向虚函数 h()在它的 vtable 中,如果是这样,那么它不应该寻找 f()Class3's vtable 并没有找到它?为什么它认为 Class1::f()Class3::h() ,它不像Class3继承自 Class1 ...为了记录,如果我们重写 Class3成为:

class Class3 : public Class1 { // publicly inherit from Class1 is only difference
    public:
    virtual void h() {
        cout << "Function h() in Class3\n";
    }
};

并向上转换为 Class1指针,然后调用 p->f()它给了我们 Class1::f()正如预期的那样,我只是不明白为什么它甚至让我们调用 p->f()什么时候Class3不继承自 Class1 .

最佳答案

此示例不好,您正在将不相关的类型相互转换。这会导致未定义的行为。

该代码利用了不同对象类型之间假定的布局相似性。 vtable 将在每个对象中的相同位置,虚函数将通过索引而不是名称找到。因此,对 Class1 的第一个虚函数的调用会通过该表生​​成调用,从而导致对 Class3 的第一个虚函数的调用。请记住,这是一个意外,并且不能由 C++ 的任何属性保证。

关于C++ 虚函数表现怪异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30488193/

相关文章:

c++ - 如何使用 SSE 高效地进行 int8/int64 转换?

c++ - 为什么内存访问这么慢?

抽象类的 Java 构造函数

multithreading - 当我在 32bit-ubuntu-12.04 下使用 g++4.7.0 测试 c++11 的新 <thread> 功能时,收到一条 'pure virtual method called' 消息

c++ - 函数返回不同类型

c++ - 从派生类重新定义在基类中定义的结构

c++ - 将静态库添加到C或C++项目的通常方法是什么?

java - 不带参数的继承构造函数

C#构造函数执行顺序

c++ - 非重写虚函数的绑定(bind)类型