#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";
}
Output:
size of Person 1
size of Faculty 8
size of Student 8
size of 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
您可以看到每个继承类的成员以及每个继承类的指针都存在(字节乱序,因为内存是小端)。我认为可以安全地假设指针指向 virtual method table。对于继承的类。
如果您删除类(class)成员,您最终会得到 VMT 指针,并且类(class)人数将与您在问题中列出的人数相同。
关于如果类是虚拟继承的,C++ 内部会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41170864/