2016-12-15 1 views
0
#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"; 
} 

Выход:C++ что происходит внутри, если класс наследуется фактически?

размера Person 1 размера факультет 8 размера Student 8 размера TA 16

, что внутри происходит в компиляторе? Я думаю, что компилятор определенно добавляет VPTR, если он добавляет VPTR, тогда он присваивает NULL?

для виртуального деструктора также компилятор добавляет VPTR, как компилятор разрешает все внутренне?

+0

См. Http://stackoverflow.com/a/991723/887836 – Alex

+0

Какой компилятор вы спрашиваете? Есть несколько. – user2079303

+0

MinGW или GCC. Мне просто нужна общая идея – ganesh

ответ

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, а размеры классов станут такими же, как те, которые вы указали в своем вопросе.

Смежные вопросы