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

来源:互联网 发布:猫咪视频软件 编辑:程序博客网 时间:2024/05/21 12:44

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

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

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

// 基类class Cd { // represents a CDdiskprivate:    char *  performers;    char *  label;    int     selections; // number ofselections    double  playtime; // playing time inminutespublic:    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;   //Titlemusicpublic:    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;                      //validpcd  =  c2;                      //validplus  =  c1;                     //ivalidplus  =  (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的基类引用,然后进行赋值。

欢迎大家留言讨论