深入搜索C++对象模型------关于对象

 /************************
//object.cpp 
************************/
  
#include <iostream>
#include <string>
using namespace std;
  
typedef void (*func_pointer)(void);
  
class Animal
{
public:
 virtual void get_vptr_addr()
 {
  cout<<" Animal::this: "<< this << endl;
 };
  
 virtual void get_vtbl_addr()
 {
  cout<<" Animal::vtbl:"<< this <<endl;
 };
  
 void call_first_virtual_func()
 {
  fun = (func_pointer)* ((int*)*(int*)this);
  cout<< "Animal::call_first_virtual_func:" << fun <<endl;
  fun();
 }
  
public:
 func_pointer fun;
private:
 int age;
 string name;
};
  
class Bear:public Animal
{
public:
 Bear(){};
 virtual void get_vptr_addr()
 {
  cout<<" Bear::this: "<< this <<endl;
 };
  
 void call_first_virtual_func()
 {
  fun = (func_pointer)*((int*)*(int*)this);
  cout<< "Bear::call_first_virtual_func:" << ((int*)*(int*)this) <<endl;
  fun();
 }
  
 void call_second_virtual_func()
 {
  fun = (func_pointer)*((int*)*(int*)this + 2);
  cout<< "Bear::call_second_virtual_func:" << ((int*)*(int*)this + 2) <<endl;
  fun();
 } 
};
  
int main()
{
 //object size:
 //1. nonstatic member data;
 //2. virtual point
 //3. struct align
  
 Animal a;
 Bear b;
 Animal *pa = &b;
 cout << "point size: "<<sizeof(pa) <<endl;
 cout << "int size: "<<sizeof(int) <<endl;
 cout << "string size: "<<sizeof(string) <<endl;
 cout << "Animal size: "<<sizeof(a) <<endl;
  
 //polymorphism
 a.call_first_virtual_func();
 b.call_first_virtual_func();
 cout<<"vtabl: "<<sizeof((int*)*(int*))<<endl;
 cout<<"vtbl fisrt func:"<<((int*)*(int*)&b)<<endl;
 cout<<"vtbl second func:"<<((int*)*(int*)&b + 1)<<endl;
 b.call_second_virtual_func();
 return 0;
}

一:关于对象大小

        只有非静态成员变量才会放在类对象中, 所以类对象大小由三个方面组成

        1. 非静态成员大小的总和

        2. 如果存在虚函数,则存在一个指向虚函数表的指针ptr.

        3. 在加上由对齐产生的额外空间

二: 关于多态

        只有指针和引用才会支持多态.

        虚函数表是属于类的所有对象,每个对象存在一个vptr指向这张表.

        目前所知,vptr总是在对象内存布局的最前面.

三:初始化列表

        如果在构造函数中对成员变量初始化的话,实际进行的是赋值操作,
        因为在进入构造函数之前,编译器调用成员变量的默认构造函数对成员变量进行了初始化。
        对于内置类型,在那里进行初始化无所谓,因为效率差不多。
        但对于自定义类型,通过初始化列表进行初始化,只需调用一次拷贝构造函数,
        而在构造函数中初始化,需要调用一次默认构造函数和一次赋值操作。

四:疑问

        改程序打印出指针的大小占8个字节,但是第二个虚函数的地址却是((int*)*(int*)this + 2),为什么不是((int*)*(int*)this + 1)求大神解答.

        

你可能感兴趣的:(C++)