重点是构造,析构,拷贝构造和赋值重载这四个函数。

2,构造函数

构造函数是特殊的成员函数,名字虽然叫做构造,但他不是用来开空间的,而是来完成初始化工作的。当实例化对象完成后,就会调用构造函数来对成员变量进行初始化。

构造函数的特点:

(1)函数名与类名相同

(2)无返回值(返回值什么都不写,void也不写)

(3)对象实例化时系统会自动调用构造函数

(4)构造函数可以重载

代码语言:javascript

AI代码解释

class Date
{
public:
    //构造函数可以重载
    Date()//无参构造函数
    {
        _year = 1;
        _month = 1;
        _day = 1;
    }
    Date(int year,int month,int day)//带参构造函数,全缺省
    {
        _year = year;
        _month = month;
        _day = day;
    }
    void print()
    {
        cout << _year << "年" << _month << "月" << _day << "日" << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};
int main()
{
    Date d1;//调用无参的构造函数
    d1.print();

    Date d2(2024, 7, 26);//调用带参的构造函数
    d2.print();

    return 0;
}

(5)如果类中没有显示定义构造函数,那么c++编译器会自动生成一个无参的默认构造函数。

如果类中定义了,编译器将不会再生成。

代码语言:javascript

AI代码解释

class Date
{
public://调用编译器自动生成的构造函数
    
    void print()
    {
        cout << _year << "年" << _month << "月" << _day << "日" << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};
int main()
{
    Date d1;//调用无参的构造函数
    d1.print();



    return 0;
}

(6)无参构造函数,全缺省构造函数,和我们不写时编译器自动生成构造函数,都叫做默认的构造函数。但这三个函数不能同时存在,不然调用的时候会存在歧义。

说明: c++中,把类型分为内置类型自定义类型内置类型就是语言提供的原生数据类型,如int,double等,自定义类型就是我们使用class/struct等关键字自己定义的类型。

(7)我们不写时,编译器自动生成的构造函数,对内置类型成员变量没有要求,是否初始化取决于编译器。而对于自定义类型成员变量,要求调用这个成员变量的默认构造函数,若是没有默认构造函数,编译器就会报错

3,析构函数

析构函数与构造函数的功能相反,它完成的不是对对象本身的销毁,不如局部对象是存在栈帧的,函数结束栈帧销毁,它就释放了,不需要我们管。c++规定,在对象销毁时,会调用析构函数,完成对象中资源清理释放工作

析构函数的特点:

(1)析构函数名是在类名前加上~

(2)无参数,无返回值

(3)一个类只能有一个析构函数,若是未显示定义,系统会自动生成默认的析构函数。

(4)对象生命周期结束时,系统会自动调用析构函数。

下面是栈的部分代码:

代码语言:javascript

AI代码解释

typedef int DataType;
class stack
{
public:
	//构造函数
	stack(size_t capacity=3)
	{
		//需要开空间
		_array = (DataType*)malloc(sizeof(DataType) * capacity);
		if (_array == nullptr)
		{
			perror("maloc fail");
			return;
		}
		_size = 0;
		_capacity = capacity;
	}
	~stack()//析构函数
	{
		//释放资源
		if (_array)
		{
			free(_array);
			_array = nullptr;
			_size = 0;
			_capacity = 0;
		}
	}
	void push(DataType x)
	{
		_array[_size] = x;
		_size++;
	}
private:
	DataType* _array;
	int _size;
	int _capacity;
};
int main()
{
	stack st;//自动调用构造

	st.push(1);
	st.push(2);
	return 0;//结束调用析构
}

(5)和构造函数类似,我们不写时,编译器自动生成的析构函数对内置类型不做处理,对自定义类型会调用它的默认析构函数。

(6)还有一点,我们显示写了析构函数,对于自定义类型,也会调用它本身的析构,也就是说无论写不写析构函数,自定义类型都会调用它本身的默认析构函数。

对于下面的代码,需要析构自定义类型。就要调用它自己的析构函数。

代码语言:javascript

AI代码解释

class Time
{
public:
	~Time()
	{
		cout << "析构Time" << endl;
	}

private:
	int _hour;
	int _minute;
	int _second;
	
};
class Date
{
private:
	int _year;
	int _month;
	int _day;

	Time _t;//自定义类型
};
int main()
{
	Date d1;
	return 0;
}

注:先调用的后析构,比如上面的Date类,对象d1,d2,先析构d1,再析构d2.

4,拷贝构造函数 

如果一个构造函数的第一个参数是自身类型的引用,且任何额外的参数都有默认值,那么这个构造函数就叫做拷贝构造函数。也就是说,拷贝构造函数是特殊的构造函数。

拷贝构造函数的特点:

(1)拷贝构造函数是构造函数的重载

(2)拷贝构造函数的第一个参数必须是类类型对象的引用,必须是引用的方式,传值的方式编译器会报错,因为语法逻辑上会引发无穷递归。(理由在后面)

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐