构造函数,拷贝构造函数,析构函数,赋值函数

例一:

class CGoods
{
    //行为,成员方法
public:
    CGoods(char *name = NULL, int amount = 0, double price = 0.0) //构造函数
    {
        if (name == NULL)
        {
            mpName = new char[1];
            *mpName = '\0';
        } 
        else
        {
            mpName = new char[strlen(name) + 1];
            strcpy(mpName, name);
        }
        
        mAmount = amount;
        mPrice = price;
    }
    ~CGoods()        //析构函数
    {
        delete[]mpName;
        mpName = NULL;
    }
    CGoods(const CGoods &src)              //拷贝构造函数
    {
        mpName = new char[strlen(src.mpName) + 1];
        strcpy(mpName, src.mpName);
        mAmount = src.mAmount;
        mPrice = src.mPrice;
    }
    void operator=(const CGoods &src)      //赋值函数
    {
        if (this == &src)
            return;

        delete[]mpName;
        mpName = NULL;

        mpName = new char[strlen(src.mpName) + 1];
        strcpy(mpName, src.mpName);
        mAmount = src.mAmount;
        mPrice = src.mPrice;
    }
private:
    char *mpName;
    int mAmount;
    double mPrice;
};

构造函数

        没有返回值、函数名字和类名称必须一样
        构造函数可以带参数,因此构造函数可以重载
        当没有提供任何构造函数的时候,编译器会给类提供默认的构造函数,函数什么也不做,是个空函数

析构函数

       没有返回值  不能带参数  不能重载

拷贝构造函数

      拷贝构造函数不能按值传递!!!

     把形参复制到实参会调用拷贝构造函数。如果允许拷贝构造函数传值,就会在拷贝构造函数内调用拷贝构造函数,形成永无休止的递归调用从而导致栈满溢出。只能将构造函数修改为A(const A&other),即把传值参数改为常量引用(传指针也不可以,只能改为引用

      用对象初始化对象,默认做的拷贝方式是,按内存字节拷贝过去,俗称浅拷贝!
      如果对象占用了外部的资源,那么默认的浅拷贝一定会发生问题的!所以,当默认的浅拷贝发生问题的时候,需要用户自己提供相应的拷贝构造函数

如果对象默认的浅拷贝发生问题,那么有哪些解决方案?
    1。提供自定义的拷贝构造函数和赋值运算符的重载函数
    2。把拷贝构造函数和赋值运算符的重载函数的声明提供在private里面

赋值函数

赋值步骤:

1,先排除自赋值;2,释放原来的资源;3,重新开辟空间,赋值

例二:

OOP的循环队列构造,析构,拷贝构造,赋值函数

class CQueue
{
public:

CQueue(int size = 10)              //构造函数
    {
        mFront = mRear = 0;
        mSize = size;
        mpQueue = new int[mSize];
    }

CQueue(const CQueue &src)               //拷贝构造函数
    {
        cout << "CQueue(const CQueue &src)" << endl;
        mFront = src.mFront;
        mRear = src.mRear;
        mSize = src.mSize;
        mpQueue = new int[mSize];
        for (int i = mFront; i != mRear; i = (i + 1) % mSize)
        {
            mpQueue[i] = src.mpQueue[i];
        }
    }

void operator=(const CQueue &src)          //赋值函数
    {
        cout << "operator=" << endl;
        // 先排除自赋值
        if (this == &src)
        {
            return;
        }
        //释放原来的资源
        delete []mpQueue;
        mpQueue = NULL;
        //重新开辟空间,赋值
        mFront = src.mFront;
        mRear = src.mRear;
        mSize = src.mSize;
        mpQueue = new int[mSize];
        for (int i = mFront; i != mRear; i = (i + 1) % mSize)
        {
            mpQueue[i] = src.mpQueue[i];
        }
    }

~CQueue()                            //析构函数
    {
        delete[]mpQueue;
        mpQueue = NULL;
    }

/*CQueue queue1 ;  //queue1被初始化为queue,queue1析构后地址被释放,queue指向变为野指针*/

/*对于对象的运算  =》   左边对象调用成员方法,把右边的对象当做参数传入
    queue2.operator=(queue1);
    void operator=(const CQueue &src) */

对象的构造和析构:

    1.对象的生成分两步  
    a.给对象分配内存   b.调用构造函数构造对象  =》 对象产生了!!!

    2.如果没有提供任何构造函数,编译器会产生默认构造函数,空函数;但是如果用户提供
    了任意构造函数,编译器就不再产生默认构造函数了!

    3.在调用默认构造函数的时候,不要添加()

    4.栈上的对象,先构造,后析构;后构造,先析构

    5.栈上的对象,定义的时候调用相应的构造函数;return处,要析构栈上的所有对象

例三:

class String
{
public:
    String(const char*str = NULL)     //普通构造函数
    {
        if (str == NULL)
        {
            m_data = new char[1];
            *m_data = 0;
        }
        else
        {
            m_data = new char[strlen(str) + 1];
            strcpy(m_data, str);
        }
    }
    String(const String&other)   //拷贝构造函数
    {
        m_data = new char[strlen(other.m_data) + 1];
        strcpy(m_data,other.m_data);
    }
    ~String()                 //析构函数
    {
        delete[]m_data;
        m_data = NULL;
    }
    String &operator = (const String &other)     //赋值函数
    {
        if (this == &other)
        {
            return *this;
        }
        delete[]&m_data;
        m_data = NULL;
        m_data = new char[strlen(other.m_data) + 1];
        strcpy(m_data, other.m_data);
    }
    
private:
    char*m_data;
};
 

其他:

int *p = new int; //分配int整形大小的空间
int *p = new int();//分配int整形大小的空间并初始化0
int *p = new int(10);//分配int整形大小的空间并初始化10
int *p = new int[10];   只开辟内存,10个大小为int整形的空间,不进行初始化
int *p = new int[10]();  不仅仅开辟内存,而且还初始化,int,数组所有元素的初值为0

用临时对象,拷贝构造新对象,此时临时对象就被C++编译器优化掉了

对象使用的三个优化规则:
1.函数参数传递对象,用引用传递,不要按值传递
2.如果你的函数返回的是对象的值,请返回一个临时对象,不要返回一个
已经存在的对象
3.接收返回对象的函数,以初始化方式接收,不要用赋值方式接收

猜你喜欢

转载自blog.csdn.net/weixin_42323413/article/details/83057390