1.只要继承不要多态
class A
{
public:
int nVal;
char ch1;
A(int Val , char ch1) :nVal(Val) ,ch1(ch1) {}
};
class B : public A
{
public:
char ch2;
B(int Val, char ch1, char ch2) : A(Val, ch1),ch2(ch2) {}
};
class C : public B
{
public:
char ch3;
C(int Val, char ch1, char ch2, char ch3) : B(Val, ch1, ch2),ch3(ch3) {}
};
int main()
{
cout << sizeof(C) << endl;
return 0;
}
①运行结果是16个字节
我们来分析一下 class A 4字节int + 1字节char + 3字节对齐 = 8字节
class B 1字节char + 3 字节对齐 = 4 字节
class C 1字节char + 3字节对齐 = 4字节
总共就是16个字节
C++语言保证 出现在派生类中的基类有其完整原样性
2.把一个子类对象 赋给基类 对象
class A* pA;
class B* pB;
pA = new class A(10, 'A');
pB = new class B(20, 'D', 'E');
*pA = *pB;


子类对象只会用自己父类的对象部分subobject来给父类对象赋值
3.把一个基类对象赋值给一个子类对象
pA = new class A(10, 'A');
pB = new class B(20, 'D', 'E');
*pB = *(class B*)pA;


4.把基类指针赋给一个派生类指针
不会出现问题,也不需要什么强转,因为根据对象模型可知,派生类最上面的那个subobject就是基类
5.把派生类指针赋给一个基类
pB = (class B *)pA;
必须要强制类型转换
而且 在使用的时候会出现问题
你用pB去调用派生类中的成员,得到的那个数 是未知值
因为pB现在和pA指向同一个地址,当基类指针 指向基类对象的时候,那么超过基类的部分是未知值。
6.我们来看一下微软的对象模型
class Point2d
{
public:
Point2d(int x = 10, int y = 20): _x(x), _y(y){}
virtual void z(int ) { }
virtual int GetZ()const { return 0.0; }
inline int GetY(void) const { return _x; }
inline int GetX(void) const { return _y; }
virtual void operator+= (const Point2d & Temp)
{
_x += Temp.GetX();
_y += Temp.GetY();
}
protected:
int _x, _y;
};
这个类里面有两个int成员变量,三个虚函数
输出显示这个类的大小是12个字节,多出的4个字节是一个指向虚函数表的指针。
给的默认形参值x是10 y是20


我们可以看到指向虚函数表的指针出现在对象模型的最上方
7.一个继承与Point2d一个类的对象模型
class Point3d : public Point2d
{
public :
Point3d(int x, int y, int z):Point2d(x, y),_z(z){}
int GetZ() const{ return _z;}
void z(int z) { _z = z; }
virtual void operator+= (const Point2d& Temp)
{
Point2d::operator+=(Temp);
_z += Temp.GetZ();
}
private:
int _z;
};

所以这里我们可以看出 为什么在单继承中 直接拿基类指针指向子类指针没有任何问题
本文详细探讨了C++中的继承和多态特性,包括基类和派生类对象的内存布局、赋值操作的影响,以及对象模型的解析。重点解释了为何在单继承中基类指针可以安全地指向派生类对象,并分析了虚函数在对象模型中的作用。此外,还讨论了类大小与虚函数表的关系,以及派生类如何扩展基类的功能。

379

被折叠的 条评论
为什么被折叠?



