构造函数和析构函数
- 构造函数:用于初始化;
- 析构函数:用于清理。
- 编译器会自动调用,用于完成对象初始化和清理工作。
- 如果不提供以上两者,那么编译器会提供,但编译器提供的构造函数和析构函数是空实现。
构造函数语法:类名(){}
* 构造函数没有返回值也不写void;
* 函数名与类名相同;
* 构造函数可以有参数,因此可以发生重载;
* 程序在调用对象是会自动调用构造函数,无需手动调用,且只会调用一次。
析构函数语法:~类名(){}
* 析构函数,没有返回值也不写void;
* 函数名与类名相同,同时在名称前加上~;
* 构造函数不可以有参数,因此不可以发生重载;
* 程序在对象销毁前会自动调用析构,无需手动调用,而且只会调用一次。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include<iostream> using namespace std; class Person{ public: Person(){ cout << "构造函数已调用!" << endl; } ~Person(){ cout << "析构函数已调用!" << endl; }
} void func(){ Person p; cout<< 111 << endl; } int main(){ func() return 0; }
|
构造函数的分类及调用
两种分类方式:
- 按参数分:有参构造和无参构造
- 按类型分为:普通构造和拷贝构造
三种调用方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #include<iostream> using namespace std; class Person{ public: Person(){ cout<< "无参构造函数调用" <<endl; } Person(int a){ age = a; cout<< "有参构造函数调用" <<endl; } Person( const Person &p){ age = p.age; cout<< "拷贝构造函数调用" <<endl; } ~Person(){ cout<< "析构函数调用" <<endl; } int age; }
void test(){ Person p1; Person p2(10); Person p3(p2);
cout<< p2.age <<endl; cout<< p3.age <<endl;
Person p4; Person p5 = Person(10); Person p6 = Person(p5);
Person p7 = 10; Person p8 = p7; } int main(){ test() cout<< <<endl; return 0; }
|
拷贝构造函数调用时机
C++中拷贝构造函数调用时机通常有三种情况:
- 使用一个已经创建完毕的对象来初始化一个新对象。
- 值传递的方式给函数参数传值。
- 以值方式返回局部对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| #include<iostream> using namespace std;
class Person{ public: int age; Person(){ cout<< "无参构造函数调用" <<endl; } Person(int a){ age = a; cout<< "有参构造函数调用" <<endl; } Person( const Person &p){ age = p.age; cout<< "拷贝构造函数调用" <<endl; } ~Person(){ cout<< "析构函数调用" <<endl; } }
void doWork(Person p){
} void doWork2(){ Person p; return p; }
void test01(){ Person p1(20); Person p2(p1); }
void test02(){ Person p; dowork(p); }
void test03(){ Person p3 = doWork2(); }
int main(){ test01(); test02(); test03(); return 0; }
|
构造函数调用规则
- 如果用户定义有构造函数,c++不再提供默认无参构造,但是会提供默认拷贝构造。
- 如果用户定义拷贝构造函数,c++不会再提供其他构造函数。
深拷贝和浅拷贝
- 浅拷贝:简单的赋值拷贝操作。
- 深拷贝:在堆区重新申请空间,进行拷贝操作。
- 如果属性有在堆区开辟的,一定要自己提供给拷贝构造函数,防止浅拷贝带来的问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include<iostream> using namespace std; class Person{ public: Person(){ cout<< "无参构造函数调用" <<endl; } Person(int a,int height){ age = a; height = new int(height); cout<< "有参构造函数调用" <<endl; } Person( const Person &p){ age = p.age; height = new int(&p.height); cout<< "拷贝构造函数调用" <<endl; } ~Person(){ if(height != NULL){ delete height; height = NULL; } cout<< "析构函数调用" <<endl; } int age; int *height; } void test01(){ Person p1(18, 160); Person p2(p1); } int main(){ test01(); return 0; }
|
初始化列表
语法:构造函数(): 属性1(值1),属性2(值2)...{}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include<iostream> using namespace std; class Person{ public: Person(string a,int b,int c):name(a),age(b),height(c){
} private: string name; int age; int height; } void test01(){ Person p1() } int main(){ test01('张三',18,185); return 0; }
|
类对象作为类成员
- C++类中的成员可以是另一个类的对象,我们称该成员为对象成品。
- 当其他类对象作为本类成员,构造时先构造类对象,再构造自身,析构的顺序与构造顺序相反。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include<iostream> #include<string> using namespace std; class Phone{ public: Phone(string name){ m_PName = name; } string m_PName;
} class Person{ public: Person(string name,string pName):m_Name(name),m_Phone(pName){ m_Name = name; } string m_Name; Phone m_Phone;
} void test(){ Person p("张三","HONER"); } int main(){ test(); return 0; }
|
静态成员
- 静态成员就是在成员变量和成员函数前加上笑键字static,称为静态成员。
- 静态成员分为:
- 静态成员变量。
- 所有对象共享同一份数据
- 在编译阶段分配内存
- 类内声明,类外初始化
- 静态成员函数。
- 所有对象共享同一个函数
- 静态成员函数只能访问静态成员变量
- 有访问权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include<iostream> using namespace std;
class Person{ public: static void func(){ cout <<"静态成员函数调用"<<endl; } static int m_A; } int Person::m_A = 0; void test(){ Person p; p.func(); Person::func(); } int main(){ cout<< <<endl; return 0; }
|