一、构造和析构(作用于类的初始化和收尾)
1、构造函数
定义:可以在类创建对象时,自动初始化类的成员变量
多个构造函数可以一起存在,参考函数重载。
①无参构造函数 格式:Test ();无返回值 函数名和类名一样 无参数
功能:在创建对象后,自动初始化对象的成员变量
②有参构造函数 : 无返回值 函数名和类名一样 无参数
传参方法:1、在创建对象时传参。Test a1(10); (优先使用)
2、Array a3 = Array(10);
// 3、Array a4 = (10);
③拷贝构造函数:Test(const Array &a)
` 1、对象传参,形参会拷贝实参,会调用一次拷贝构造函数
2、Test a2(a1);
2、析构函数
定义:在函数运行结束后,自动执行,用于释放类创建的对象的资源
析构函数 格式:无返回值 ~加上类的名 无参数
#include <iostream>
#include <cstdlib>
using namespace std;
class Array
{
private:
int *data; //数组的起始地址
int size; //数组的容量
public:
Array(); //无参构造函数 函数名和类名一样 没有返回值 完成对象的初始化操作
Array(int s); //有参构造函数 可以一起存在,参考函数的重载
Array(const Array &a); //拷贝构造函数
void setVal(int Index,int val);
int getVal(int Index);
~Array(); //析构函数 函数名是~加上类名 没有参数 没有返回值
};
Array::Array()
{
cout << "Array的无参构造函数" << endl;
size = 5;
data = (int *)malloc(sizeof(int) * size);
}
void Array::setVal(int Index,int val)
{
data[Index] = val;
}
int Array::getVal(int Index)
{
return data[Index];
}
Array::~Array()
{
cout << "Array析构函数" << endl;
if(data != NULL)
{
free(data);
}
}
Array::Array(int s)
{
cout << "Array的有参构造函数" << endl;
size = s;
data = (int *)malloc(sizeof(int) * s);
}
Array::Array(const Array &a)
{
cout << "Array拷贝构造函数" << endl;
}
void f(Array a) //把a1赋值到a
{
}
int main()
{
Array a1; //创建对象时,自动调用构造函数
Array a2(10); //自动构造有参函数
Array a3 = Array(10);
Array a4 = (10);
for(int i = 0;i < 5;i++)
{
a1.setVal(i,i + 1);
}
for(int i = 0;i < 5;i++)
{
cout << a1.getVal(i) << " ";
}
cout << endl;
cout << "*********" << endl;
f(a1); //函数传参对象会调用拷贝构造函数
Array a5(a2); //调用拷贝构造函数 用a2构造a5
return 0; //释放对象时,自动调用析构函数
}
3、默认构造函数
二个特殊的构造函数
1)默认无参构造函数
当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空
2)默认拷贝构造函数
当类中没有定义拷贝构造函数时,编译器默认提供一个默认拷贝构造函数,简单的进行成员变量的值复制
#include <iostream>
using namespace std;
class Test1
{
public:
};
class Test2
{
public:
Test2()
{
cout <<"Test2 无参构造函数" << endl;
}
};
class Test3
{
public:
Test3(int a)
{
}
};
class Test4
{
public:
Test4(const Test4 &t)
{
}
};
int main()
{
Test1 t1; //编译器会默认提供无参构造函数
Test2 tt(t2); //编译器提供默认的拷贝构造函数 浅拷贝
Test2 t2; //一旦提供了无参构造函数,编译器不再提供默认无参构造函数
//Test3 t3; //一旦提供了有参构造函数,编译器不再提供默认的无参构造函数
//Test4 t4; //一旦提供了拷贝构造函数,编译器不再提供无参构造函数
return 0;
}
二、深拷贝和浅拷贝
只做简单的拷贝赋值:浅拷贝:只是把地址复制了下,两个对象指向同一个地址,delete会删除两次
解决浅拷贝问题:深拷贝
#include <iostream>
#include <cstdlib>
using namespace std;
class Array
{
private:
int *data;
int size;
public:
Array(int s);
Array(const Array &a); //深拷贝
~Array();
};
Array::Array(int s)
{
cout << "Array有参构造函数"<< endl;
size = s; //每个对象里的size
data = (int *)malloc(sizeof(int) * size);
}
Array::Array(const Array &a)
{
cout << "Array 深拷贝"<<endl;
size = a.size; //相当于a2的size
data = (int *)malloc(sizeof(int) * size);
for( int i = 0;i < size;i++)
{
data[i] = a.data[i];
}
}
Array::~Array()
{
cout << "Array析构函数"<< endl;
if(data != NULL)
{
free(data);
}
}
int main()
{
Array a1(10);
Array a2(a1); //默认拷贝函数为浅拷贝
return 0;
}
三、匿名对象
class Test
{
{;
格式:Test(); //匿名对象 执行完这一行就被释放
#include <iostream>
using namespace std;
class Test
{
public:
Test()
{
cout << "Test 无参构造函数" << endl;
}
~Test()
{
cout<< "Test 析构函数" << endl;
}
};
int main()
{
Test(); //匿名对象,本行代码执行完成,立马被释放
Test();
return 0;
}
四、多个对象的构造和析构
1、对象初始化链表
概念:在对象被创建时(在构造函数执行前),对对象的变量进行赋值
2、使用场景
1、类对象作为成员变量,并且该类没有提供无参构造函数
2、成员变量被const修饰
#include <iostream>
using namespace std;
class Date
{
private:
int year;
int month;
int day;
public:
/*
Date()
{
year = 1999;
month = 1;
day = 1;
}*/
Date(int y,int m,int d)
{
year = y;
month = m;
day = d;
}
};
//对象初始化链表:1、类对象作为成员变量,并且该类没有提供无参构造函数 2、成员变量被const修饰(初始化和赋值不同)
class Student
{
private:
int a;
const int id;
Date Birth;
public:
Student(int i,int y,int m,int d) : Birth(y,m,d),id(i),a(1) //对象初始化链表
{
}
};
int main()
{
Student s1(1,1999,1,1);
return 0;
}
被const修饰(初始化和赋值不同)