#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,编译器如何在内部解析所有内容?
答案 0 :(得分:1)
在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。
如果删除类成员,最终会得到VMT指针,类大小将与您在问题中列出的类相同。