C++ 基类与派生类之间的相互引用、赋值问题

C++ 基类与派生类之间的相互引用、赋值问题

这是我第一次真正的自己写C++的文章,前两天在网上找基类与派生类之间的赋值,引用,指针之间的问题是没有找到一个详细介绍的,这也正是我决定写这篇文章的目的。关于显式复制构造函数的声明、定义,转换操作符的声明、定义都在附件中,里面是一个完整的程序。

源程序下载链接:http://download.csdn.net/detail/qq252101792/4196000

// 基类
class Cd { // represents a CDdisk
private:
    char *  performers;
    char *  label;
    int     selections; // number ofselections
    double  playtime; // playing time inminutes
public:
    Cd();
    Cd(char * s1, char * s2, int n, double x);
    Cd(const Cd & d);
    virtual ~Cd();
    virtual void Report() const; // reports all CDdata
    Cd & operator=(const Cd & d);
};
 
//派生类
class Classic:public Cd{
private:
    char * master;   //Titlemusic
public:
    Classic();
    Classic(char *s1, char *s2, char *s3, int n, double x);
    Classic(const Classic &p);
    Classic(const Cd      &d);
    virtual ~Classic();
    virtual void Report() const;
    Classic & operator=(const Classic &p);
    Classic & operator=(const Cd      &d);
};


定义下面2个变量:

   

    Cd c1("Beatles", "Capitol", 14, 35.5);
    Classic c2 = Classic("Piano Sonatain B flat, Fantasia in C",  "AlfredBrendel", "Philips", 2, 57.17);

 一、指针和引用兼容性

Cd *pcd ;    
Classic  *plus ;
pcd  =  c1;                      //valid
pcd  =  c2;                      //valid
plus  =  c1;                     //ivalid
plus  =  (Classic *)c1;       //valid

在C++中,将派生类引用或指针转换为基类引用或指针被称为“向上强制转换”,这使公有继承不需要进行显式强制类型转换。Classic对象都是Cd对象,因为它继承了Cd对象的所有数据成员和成员函数,所以对Cd对象执行的任何操作都适用于Classic对象,而不必担心会导致任何问题。

相反的过程,将基类引用或者指针转换为派生类引用或指针被称为“向下强制转换”,如果不进行显式强制类型转换,向下强制转换是不允许的。继承是不可逆的。派生类增加了新的数据成员,使用这些数据成员的成员函数不能应用于基类,基类没有这些属性和行为。

、复制构造函数

凡是在构造函数中使用 new操作申请内存的类中,都要定义显式的复制构造函数,进行深度复制。C++默认的复制构造函数进行浅复制,复制的是成员的值:例如str = “hello world!”,浅复制只复制str的地址,而深度复制是复制str所指向的整个字符串。

使用同类对象构造同类对象的不存在任何问题,除非你的构造函数本身是错误的,这只能埋怨你自己不细心咯!

1、  使用派生类对象  复制构造   基类对象:

Cd  copyCon(c2);

C++允许这种操作,将classic中的Cd数据成员复制到新的变量中,忽略classic中新增加的成员。如果Cd的复制构造函数中没有使用new则不需要显式定义这种复制构造函数;

2、  使用基类对象  复制构造 派生类对象:

Classic  copyCd(c1);

调用基类的复制构造函数初始化派生类中基类成员的值,然后对派生类的特有成员分别进行赋值。需要注意的是:这种复制构造函数只将基类引用作为唯一参数。

三、赋值

         和复制构造函数类似,如果构造函数中使用new操作申请内存的类中,都要重载赋值运算符,以进行深度复制,避免系统默认的浅复制所带来的bug。

1、将基类对象  赋给  派生类对象:

  

Classic newPlus;
 newPlus  =  c1;

C++不允许这种转换操作,除非定义转换操作符,此处是赋值(=)操作符;

①  如果派生类有显式定义用基类构造派生类的复制构造函数,而没有定义转换复制操作符,则上述赋值操作将调用派生类的复制构造函数来完成赋值操作;(这一条是我自己在VC上单步调试得到的结果,至于其它编译器我不确定是否是这样。)

②  有定义转换操作符,则将调用转换操作符进行赋值操作

2  将派生类对象  赋给  基类对象;

        

         Cd newCd;
         newCd =  c2;

         C++将调用基类的赋值运算符,建立起对c2的基类引用,然后进行赋值。

欢迎大家留言讨论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值