13 复制控制 学习

1.前言
复制控制通常指类的复制构造函数,赋值操作运算符,析构函数
1.1
复制构造函数
引入复制构造函数是为了让类的对象直接生成另一个对象,同时把此对象的数据复制到另一个对象中
如果类中没有实现复制构造函数,编译器自动添加一个,
如果我们不需要,则把它明确的禁止,禁止方法是在private声明一个
2.定义
2.1
复制构造函数的2种方法实现
base(const base& org):x(org.x),y(org.y){} //
用初始化列表方式实现
base(const base& org){x=org.x; y=org.y;} //
用传统函数方式初始化成员
复制构造函数没有返回值,是一种特别的构造函数,自动可以用构造函数的初始化列表达式
demo c(b); //
触发调用复制构造函数 
2.2赋值操作运算符
通过重载运算符=,达到类的对象之间可以赋值功能,简化类对象的操作
但返回值必须有this指针的指向的引用"*this"
b=c;          //
触发调用赋值操作运算符
2.3
代码例子:

#include <iostream>
class demo
{
public:
    demo():x(0),y(0){}//
无参数的构造函数
    demo(int a1,int b1):x(a1),y(b1){}//
有默认值参数的构造函数
    void setxy(int a=0,int b=0){x=a; y=b;} //
修改x,y成员
    void print(){std::cout<<" x="<<x<<" y="<<y<<"/n";}
    //3
个复制控制函数在一起实现
    demo(const demo& org):x(org.x),y(org.y){} //
复制构造函数
    demo& demo::operator=(const demo& rhs){x=rhs.x; y=rhs.y; return *this;} //
赋值操作运算符
    ~demo(){}//
析构函数
protected:
    int x;
    int y;
};

class derived :public demo{
public: 
    //
派生类构造函数
    derived():demo(),z(0){}//
无参数的构造函数
    derived(int a2,int b2,int c2):demo(a2,b2),z(c2){}//
有默认值参数的构造函数

    //重写print()
    void print(){std::cout<<" x="<<x<<" y="<<y<<" z="<<z<<"/n";}
    //
派生类复制控制(复制构造函数,赋值运算符,析构函数)
    derived(const derived& org):
demo(org),z(org.z){} //复制构造函数 ??
    derived& derived::operator=(const derived& rhs)//赋值操作运算符
    {
        if (this!=&rhs){
        demo::operator=(rhs); //
调用基类的=运算
        z=rhs.z;   
    }
        return *this;
    }
    ~derived(){}//
析构函数

private:
    int z;
};

int main()
{
//
基类调用
    std::cout<<"base class demo/n";
    demo b;    //
此时bx,y都为0
    b.print(); //x=0,y=0
    b.setxy(5,22); //
此时bx
    b.print(); //x=5,y=22
    //
调用复制构造函数用B的数据直接去初始化
    demo c(b); //
对象cx,y由原来的0变成5,22
    c.print(); //x=5,y=22
    c.setxy(10,100);//
修改c对象的x,y分别为10,100
    //
调用赋值操作运算符
    b=c;          //
c的成员值直接赋值到b对象的所有成员
    c.print(); //x=10,y=100
    std::cout<<"derived class demo/n";
    //
派生类调用
    derived d1(11,22,33),d2;
    d1.print(); //x=11,y=22,z=33
    d2.print(); //x=0,y=0,z=0
    d2=d1;
    d2.print(); //x=11,y=22,z=33
    d2.setxy(2,8);
    d2.print(); //x=2,y=8,z=33
    derived d3(d2);
    d3.print(); //x=2,y=8,z=33
    return 0;
}

//以上代码用VS2005测试通过
3.基类与派生类
原则上基类复制控制由基类的成员函数完成,派生类由派生类完成在派生类进行复制控制时,要特别注意要把从基类继承而来的成员也要初始化或者赋值,因为名称一样,它在派生类找到这个函数名称后就不会再往上查找基类的函数,这直接引发派生类函数"覆盖"了基类的同名函数,从基类往派生类产现来看,又叫做派生类的函数"重写"结果我们的选择:
只能在派生类的复制控制函数加上调用基类的复制构造函数
只能在派生类的 赋值操作符加上调用基类的赋值操作符
3.1
派生类的复制构造函数实现
//
基类
class derived :public demo{
//...
完整代码见上面
};

4.设计指导
在基类的复制控制:有一个"三实现"原则,复制构造函数,赋值运算符,析构函数只要出现一个,就尽量实现三个在派生类的复制控制,请直接调用基类的复制函数来实现不同的分工在派生类的析构函数只调用派生类,基类也只调用基类的

摘自互联网

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值