C 如果实际上是继承了类,则内部发生了什么

C++ what internally happens if class is inherited virtually?

本文关键字:内部 发生了 什么 如果 实际上 继承      更新时间:2023-10-16
#include<iostream>
using namespace std;
class Person {
public:
    Person(int x) { cout << "Person::Person(int ) called" << endl; }
    //Person()   { cout << "Person::Person() called" << endl; }
};
class Faculty : virtual public Person {
public:
    Faculty(int x):Person(x) {
    cout<<"Faculty::Faculty(int ) called"<< endl;
    }
};
class Student : virtual public Person {
public:
    Student(int x):Person(x) {
        cout<<"Student::Student(int ) called"<< endl;
    }
};
class TA : public Faculty, public Student {
public:
    TA(int x):Student(x), Faculty(x),Person(x) {
        cout<<"TA::TA(int ) called"<< endl;
    }
};
int main() {
    cout<<"size Person "<<sizeof(Person)<<"n";
    cout<<"size Faculty "<<sizeof(Faculty)<<"n";
    cout<<"size Student "<<sizeof(Student)<<"n";
    cout<<"size TA "<<sizeof(TA)<<"n";
}

输出:

人的大小1

教师的大小8
学生的大小8
TA 16

的大小

编译器内部发生了什么?我认为编译器肯定会添加VPTR,如果它添加了VPTR,那么它是否分配给NULL?

对于虚拟驱动器,编译器还添加了VPTR编译器如何在内部解决所有内容?

在C 对象中是可寻址的,因此必须具有与之关联的大小。在Person的情况下,没有成员变量,因此无需为实例化对象分配任何空间。但是,由于它必须具有一个尺寸,因此编译器的大小为1。

如果我将成员添加到每个类中,我们可以在每个对象中打印数据并查看发生的事情:

class Person {
public:
    Person(int x) {
        cout << "Person::Person(int ) called" << endl;
        y = 0xAAAAAAAAAAAAAAAA;
    }
    volatile unsigned long long int y;
};
class Faculty : virtual public Person {
public:
    Faculty(int x):Person(x) {
        cout<<"Faculty::Faculty(int ) called"<< endl;
        y = 0xBBBBBBBBBBBBBBBB;
    }
    volatile unsigned long long int y;
};
class Student : virtual public Person {
public:
    Student(int x):Person(x) {
        cout<<"Student::Student(int ) called"<< endl;
        y = 0xCCCCCCCCCCCCCCCC;
    }
    volatile unsigned long long int y;
};
class TA : public Faculty, public Student {
public:
    TA(int x):Person(x), Student(x), Faculty(x) {
        cout<<"TA::TA(int ) called"<< endl;
        y = 0xDDDDDDDDDDDDDDDD;
    }
    volatile unsigned long long int y;
};

使用以下功能将分配给每个类实例化对象的数据打印出:

void print_obj(void* obj, unsigned size) {
    unsigned char * ptr = (unsigned char *)obj;
    for(unsigned i = 0; i < size; i++)
        printf("%02X", ptr[i]);
}

这是输出(GCC版本4.9.2):

Printing Person
AAAAAAAAAAAAAAAA
Printing Faculty
9814400000000000BBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA
Printing Student
7814400000000000CCCCCCCCCCCCCCCCAAAAAAAAAAAAAAAA
Printing TA
D813400000000000BBBBBBBBBBBBBBBBF013400000000000CCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDAAAAAAAAAAAAAAAA

您可以看到每个继承类的成员以及每个继承类的指针都存在(字节是故障的,因为内存很小)。我认为可以肯定地假设指针指向继承类的虚拟方法表。

如果您删除了类成员,则最终会得到VMT指针,并且班级的大小与您在问题中列出的指针相同。