继承与data member之单一继承

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

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;
};

在这里插入图片描述
所以这里我们可以看出 为什么在单继承中 直接拿基类指针指向子类指针没有任何问题

8.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值