CPP_类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数

类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数

// person.h
#ifndef _PERSON_H_
#define _PERSON_H_

class Person{
    public :
        Person();
        Person(int myage, char *myname);
        Person(const Person &a);
        Person& operator=(const Person& other);
        ~Person(void);

        void set_age(int myage);
        int get_age(void) const;
        void set_other_age(Person &a, int b); 
        void print() const;

    private:
        int age;
        char *name;
};

#endif
// person.cc
#include "person.h"

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

Person::Person():age(10), name(NULL)
{
    //nothing   
    cout<<"no param construct!"<<endl;
}

Person::Person(int myage, char *myname)
{
    age = myage;
    if(myname != NULL){
        name = new char[strlen(myname) + 1];
        this->print();
        strcpy(name, myname);
    }
    cout<<"param construct!"<<endl;
}

Person::Person(const Person &a)
{
    cout <<"copy constructor!"<<endl;
    if(a.name != NULL){
        name = new char[strlen(a.name)+1];
        this->print();
        strcpy(name, a.name);
        age = a.age;
    } else {
        name = NULL;
        age = 10;
    }
}
Person& Person::operator=(const Person &a)
{
    cout <<"= constructor!"<<endl;
    if(&a == this){
        return *this;
    }

    if(name != NULL){
        delete [] name;
        name = NULL;
    }
    if(a.name != NULL){
        name = new char[strlen(a.name)+1];
        this->print();
        strcpy(name, a.name);
        age = a.age;
    } else {
        name = NULL;
        age = 10;
    }

    return *this;
}


Person::~Person()
{
    if(NULL != name){
        delete [] name;
        name = NULL;
    }
    cout<<"destructor!"<<endl;
}
void Person::set_age(int myage)
{
    age = myage;
}

int Person::get_age(void) const
{
    return age;
}

void Person::set_other_age(Person& a, int b)
{
    a.age = b;
    //a.set_age(b);
}

void Person::print() const
{
    if(name != NULL)
        cout <<"value:" << name;
    cout<< " name=" << static_cast<void*> (name) << endl;
}
// main.cc
#include "person.h"

#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
    Person a(11, "xiaohhhhh");  
    Person b(13, "mingttttt");
    Person m;

    m = b;
    a.print();
    b.print();
    m.print();

    Person n(13, "qing");
    b=n;
    a=n;
    m=n;
    a.print();
    b.print();
    m.print();

    return 0;
}

构造函数、析构函数和赋值函数是类最重要的函数,被称为The Big Three。
与其他成员函数相比,The big three特殊之处在于,如果代码中没有提供这些函数的实现,C++编译器自动合成缺省的函数实现。
有指针成员变量的类一定要提供The Big Three的实现,即使没有指针变量,作为良好的编程习惯也应该提供The Big Three的实现。

1. 构造函数

和类同名,无返回值,用来初始化类的对象。
构造函数可重载。
编译器提供默认无参构造函数,若声明新的,则采用新的构造函数。一般多应创建一个无参的构造函数,因为创建了有参构造函数后,默认的无参构造函数被覆盖。
构造函数在对象创建后马上调用。
Person a; //调用无参构造函数
Person a(20, "Xiaoming"); //调用两参构造函数
Person(int age=0, const char *name = NULL);构造函数,相当于创建无参或两参构造函数。

2.拷贝构造函数

Person(const Person &a);
如果没有提供拷贝构造函数,编译器会默认提供一个(执行逐个成员初始化,将新对象初始化为原对象的副本,这里的逐个是指编译器将现有对象的每个非static成员,依次复制到正在创建的对象)。
如果类有指针成员变量或类数据成员管理资源(如打开一个文件),默认构造函数并不会自动分配指针所指向的空间(默认构造函数仅提供浅拷贝),需要添加拷贝构造函数实现深拷贝。
默认拷贝构造函数实现浅拷贝:指针成员变量指向同一存储区域,而不是重新分配区域再赋值(深拷贝)。
如果想禁止一个类的拷贝构造,需要将拷贝构造函数声明为private。

3. 析构函数

析构函数不可重载。
类名前加~的函数,无参数,无返回值。
先调用析构函数->后销毁对象。
默认的析构函数不会释放指针成员变量分配的内存区域,可能造成内存泄露。有指针成员变量时必须实现析构函数。

4. 赋值函数

Person& operator=(const Person& other);
基本与拷贝构造等价。如果想禁止一个类的赋值函数,需要将拷贝构造函数声明为private。
Person b=a; //拷贝构造函数
Person b;
b = a; //赋值函数 operator=

5. 构造函数的初始化列表

const变量必须用初始化列表进行初始化。
Person():age(10), name(NULL)中":age(10),name(NULL)"为初始化列表。

6. set_other_age()同一类的不同对象可以访问其他对象的私有数据。

7. this指针

每个成员方法都包含一个隐藏参数this,this是一个对象的指针,指向调用函数的对象。
判断自赋值:

if(this == &a){
return *this;
}
原文地址:https://www.cnblogs.com/embedded-linux/p/9613271.html