空类大小及指针转换(多继承)
2018-03-02 16:38
204 查看
先得出结论:
1. 空类大小为1(仅标识类的存在),如果空类中加了virtual关键字则是4(虚函数表指针)。
2. 子类指针转父类时, 强转、static_cast、dynamic_cast效果一样!
3. 强转时,A,B 指针值 与 C的指针值可能相同或不同!
4.虚函数原理,请查阅http://blog.csdn.net/hq354974212/article/details/76985270
情形一:class A
{
public:
void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
void AAA()
{
printf("C::AAA();\n");
}
void BBB()
{
printf("C::BBB();\n");
}
};此处C的大小并不是想象中的1+1=2,而是1,因为空类只需要占1字节即可!
这里A指针的地址与C指针地址一样!
情形二:
class A
{
public:
virtual void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
void AAA()
{
printf("C::AAA();\n");
}
void BBB()
{
printf("C::BBB();\n");
}
};此处C的大小并不是想象中的4(虚函数表指针)+1=5,而是4,因为C已经不为空类了!
这里A指针的地址与C指针地址一样!
情形三:class A
{
public:
void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
virtual void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
void AAA()
{
printf("C::AAA();\n");
}
void BBB()
{
printf("C::BBB();\n");
}
};
此处C的大小并不是想象中的4(虚函数表指针)+1=5,而是4,因为C已经不为空类了!
这里B指针的地址与C指针地址一样!
情形四:
class A
{
public:
virtual void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
virtual void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
void AAA()
{
printf("C::AAA();\n");
}
void BBB()
{
printf("C::BBB();\n");
}
};此处C的大小是8(A虚表指针,B虚表指针)
这里A指针的地址与C指针地址一样!
情形五:
class A
{
public:
void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
virtual void AAA()
{
printf("C::AAA();\n");
}
void BBB()
{
printf("C::BBB();\n");
}
};此处C的大小是4(C虚表指针)+1+1,字节对齐后为8!
这里A指针,B指针的地址都与C指针地址不一样!
情形六:
class A
{
public:
void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
void AAA()
{
printf("C::AAA();\n");
}
virtual void BBB()
{
printf("C::BBB();\n");
}
};此处C的大小是4(C虚表指针)+1+1,字节对齐后为8!
这里A指针,B指针的地址都与C指针地址不一样!
情形七:
class A
{
public:
void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
virtual void AAA()
{
printf("C::AAA();\n");
}
virtual void BBB()
{
printf("C::BBB();\n");
}
};此处C的大小是4(C虚表指针)+1+1,字节对齐后为8!
这里A指针,B指针的地址都与C指针地址不一样!
以上七种情形用同一份测试代码:int main()
{
C c;
printf("三个类的大小:C:%d A:%d B:%d \n", sizeof(C) ,sizeof(A),sizeof(B));
printf("子类指针地址:%p\n",&c);
A *pA1 = ( A *)&c;
A *pA2 = static_cast< A *>(&c);
A *pA3 = dynamic_cast< A *>(&c);
printf("父类A指针地址:%p, %p, %p\n", pA1,pA2,pA3);
pA1->AAA();
B *pB1 = ( B *)&c;
B *pB2 = static_cast< B *>(&c);
B *pB3 = dynamic_cast< B *>(&c);
printf("父类B指针地址:%p, %p, %p\n", pB1, pB2, pB3);
pB1->BBB();
return 0;
}
1. 空类大小为1(仅标识类的存在),如果空类中加了virtual关键字则是4(虚函数表指针)。
2. 子类指针转父类时, 强转、static_cast、dynamic_cast效果一样!
3. 强转时,A,B 指针值 与 C的指针值可能相同或不同!
4.虚函数原理,请查阅http://blog.csdn.net/hq354974212/article/details/76985270
情形一:class A
{
public:
void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
void AAA()
{
printf("C::AAA();\n");
}
void BBB()
{
printf("C::BBB();\n");
}
};此处C的大小并不是想象中的1+1=2,而是1,因为空类只需要占1字节即可!
这里A指针的地址与C指针地址一样!
情形二:
class A
{
public:
virtual void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
void AAA()
{
printf("C::AAA();\n");
}
void BBB()
{
printf("C::BBB();\n");
}
};此处C的大小并不是想象中的4(虚函数表指针)+1=5,而是4,因为C已经不为空类了!
这里A指针的地址与C指针地址一样!
情形三:class A
{
public:
void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
virtual void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
void AAA()
{
printf("C::AAA();\n");
}
void BBB()
{
printf("C::BBB();\n");
}
};
此处C的大小并不是想象中的4(虚函数表指针)+1=5,而是4,因为C已经不为空类了!
这里B指针的地址与C指针地址一样!
情形四:
class A
{
public:
virtual void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
virtual void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
void AAA()
{
printf("C::AAA();\n");
}
void BBB()
{
printf("C::BBB();\n");
}
};此处C的大小是8(A虚表指针,B虚表指针)
这里A指针的地址与C指针地址一样!
情形五:
class A
{
public:
void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
virtual void AAA()
{
printf("C::AAA();\n");
}
void BBB()
{
printf("C::BBB();\n");
}
};此处C的大小是4(C虚表指针)+1+1,字节对齐后为8!
这里A指针,B指针的地址都与C指针地址不一样!
情形六:
class A
{
public:
void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
void AAA()
{
printf("C::AAA();\n");
}
virtual void BBB()
{
printf("C::BBB();\n");
}
};此处C的大小是4(C虚表指针)+1+1,字节对齐后为8!
这里A指针,B指针的地址都与C指针地址不一样!
情形七:
class A
{
public:
void AAA() { printf("A::AAA();\n"); }
};
class B
{
public:
void BBB() { printf("B::BBB();\n"); };
};
class C :public A, public B
{
public:
virtual void AAA()
{
printf("C::AAA();\n");
}
virtual void BBB()
{
printf("C::BBB();\n");
}
};此处C的大小是4(C虚表指针)+1+1,字节对齐后为8!
这里A指针,B指针的地址都与C指针地址不一样!
以上七种情形用同一份测试代码:int main()
{
C c;
printf("三个类的大小:C:%d A:%d B:%d \n", sizeof(C) ,sizeof(A),sizeof(B));
printf("子类指针地址:%p\n",&c);
A *pA1 = ( A *)&c;
A *pA2 = static_cast< A *>(&c);
A *pA3 = dynamic_cast< A *>(&c);
printf("父类A指针地址:%p, %p, %p\n", pA1,pA2,pA3);
pA1->AAA();
B *pB1 = ( B *)&c;
B *pB2 = static_cast< B *>(&c);
B *pB3 = dynamic_cast< B *>(&c);
printf("父类B指针地址:%p, %p, %p\n", pB1, pB2, pB3);
pB1->BBB();
return 0;
}
相关文章推荐
- 空类大小及指针转换(单继承)
- C++多重继承下的指针类型转换
- c++函数指针、虚继承大小、类型转换、C特殊情况记录
- 07_类类型转换、继承、虚基类、 静态联编 与 动态联编、父子类指针、虚函数、类模板
- 【C++的探索路11】继承与派生之拓展篇--多形式派生以及派生类指针转换
- C++多重继承下的指针类型转换
- 空类,虚函数类,虚继承类的空间大小
- smart pointer(灵巧指针)和继承类到基类的类型转换
- 通过malloc动态申请整形大小的内存,把地址强制转换成整形指针
- B继承自A,A指针无法隐式转换为B指针,函数参数只管指针类型,与实际指向对象无关
- C++:C++ 空类的大小及相关继承类的大小
- 多重继承与void*指针转换问题的分析
- C++多重继承下的指针类型转换
- C++中各种空类以及继承空类后的sizeof大小
- C++多重继承下的指针类型转换
- C++多重继承下的指针类型转换
- C++多重继承子类和父类指针转换过程中的一个易错点
- c++函数指针、虚继承大小、类型转换、C特殊情况记录
- 类大小测试(空类、带含静态和非含、虚和非虚的单继承和多继承等)
- C++多重继承下的指针类型转换