构造函数
C++编译器提供了构造函数来处理对象的初始化
class Test
{
public :
Test(); //构造函数函数名和类名一样 没有返回值 void都不可以
private :
int num_;
};
构造函数的分类
1无参构造函数
2有参构造函数
3拷贝构造函数 (用一个构造函数初始化另一个构造函数对象)
拷贝构造函数
(1) 什么是拷贝构造函数
拷贝构造函数是一种特殊的构造函数,其形参为本类的对象引用。
(2) 拷贝构造函数的形式
class 类名
{
public : 类名(形参);//构造函数
类名(类名 &对象名);//拷贝构造函数 ...
类名(const 类名 &对象名);//拷贝构造函数 ... 带有const修饰的
};
#include <iostream>
using namespace std;
class A
{
public:
A();
A(const A & a);
int fun();
};
A::A()
{
cout << "普通的构造函数" << endl;
}
A::A(const A & a)
{
cout << "拷贝构造函数" << endl;
}
int A::fun()
{
return 5;
}
int main()
{
return 0;
}
(3)拷贝构造函数的使用 什么情况下会使用到拷贝构造函数
拷贝函数使用奥义 : 在对象还没有被实例化的情况赋值会使用到拷贝构造函数
#include <iostream>
using namespace std;
class A
{
public:
A(int a);
A(const A & a);
public:
int num;
};
void Test(A a)
{
cout << "a的num = " << a.num << endl;
}
A Test2()
{
A a4(7);
cout << "a4的num = " << a4.num << endl;
return a4;
}
int main()
{
A a1(6); //使用的构造函数
cout << "a1的num = " << a1.num << endl;
A a2 = a1; //第一种使用拷贝构造函数 初始化
cout << "a2的num = " << a2.num << endl;
A a3(a1); //第二种使用拷贝构造函数
cout << "a3的num = " << a3.num << endl;
Test(a1); //第三种使用拷贝构造函数 用实参初始化形参的时候会调用拷贝构造函数
Test2(); //第四种使用拷贝构造函数 返回时执行了拷贝构造函数创造了一个匿名对象 在生命周期结束的时候调用两次析构函数
return 0;
}
A::A(int a)
{
this->num = a;
cout << "普通的构造函数" << endl;
}
A::A(const A & a)
{
this->num = a.num;
cout << "拷贝构造函数" << endl;
}
有关匿名对象去和留的知识点
用匿名对象 初始化 一个同类型的的对象(Test t1 = f()) 匿名对象被转换成有名对象
赋值 一个同类型的对象 t2 = f() 匿名对象会被析构函数销毁
构造函数初始化列表
以上我们在使用构造函数初始化类的成员变量是都是在构造函数内部完成的。
A::A(int a)
{
this->num = a;
cout << "普通的构造函数" << endl;
}
但是我们还可以使用函数列表来进行初始化。
推荐在构造函数初始化列表中进行初始化,其作用就是在一个类中有组合类的时候使用,给组合类中参数传参。
#include <iostream>
using namespace std;
class A
{
public:
A(int a) {
cout << "A的构造函数" << endl;
my_a = a;
cout << "my_a = " << this->my_a << endl;
}
~A() {
cout << "A的析构函数" << endl;
}
int my_a;
};
class B {
public:
B(int q, int w, int e, int r, int u) :a1(q), a2(w), b1(e), b2(r), a3(u) { //这就是构造函数使用参数列表来进行初始化
cout << "B的构造函数" << endl;
cout << "b1 = " << this->b1 << endl;
cout << "b2 = " << this->b2 << endl;
}
~B() {
cout << "B的析构函数" << endl;
}
A a1; //组合类 是优先被初始化的
A a2;
A a3;
int b1; //这里变量的声明顺序决定了初始化的顺序,参数列表的顺序没有用
int b2;
};
int main()
{
B b1(2, 3, 4, 5, 6);
return 0;
}
构造函数和析构函数的综合练习
//对象做函数参数
//1 研究拷贝构造
//2 研究构造函数,析构函数的调用顺序
//总结 构造和析构的调用顺序
#include "iostream"
using namespace std;
class ABCD
{
public:
ABCD(int a, int b, int c)
{
this->a = a;
this->b = b;
this->c = c;
printf("ABCD() construct, a:%d,b:%d,c:%d \n", this->a, this->b, this->c);
}
~ABCD()
{
printf("~ABCD() construct,a:%d,b:%d,c:%d \n", this->a, this->b, this->c);
}
int getA()
{
return this->a;
}
protected:
private:
int a;
int b;
int c;
};
class MyE
{
public:
MyE():abcd1(1,2,3),abcd2(4,5,6),m(100)
{
cout<<"MyD()"<<endl;
}
~MyE()
{
cout<<"~MyD()"<<endl;
}
MyE(const MyE & obj):abcd1(7,8,9),abcd2(10,11,12),m(100)
{
printf("MyD(const MyD & obj)\n");
}
protected:
//private:
public:
ABCD abcd1; //c++编译器不知道如何构造abc1
ABCD abcd2;
const int m;
};
int doThing(MyE mye1)
{
printf("doThing() mye1.abc1.a:%d \n", mye1.abcd1.getA());
return 0;
}
int run2()
{
MyE myE;
doThing(myE);
return 0;
}
//
int run3()
{
printf("run3 start..\n");
ABCD(400, 500, 600); 这是一个匿名对象,没有接收所以生命周期只存在这一行
ABCD abcd = ABCD(100, 200, 300);
//若直接调用构造函数呢?
//想调用构造函数对abc对象进行再复制,可以吗?
//在构造函数里面调用另外一个构造函数,会有什么结果?
printf("run3 end\n");
return 0;
}
int main()
{
run2(); <-单独运行的时候类的构造函数和析构函数的调用顺序
run3();
system("pause");
return 0;
}