构造与析构(C++)
2023-12-24 22:36:18
2.2 构造与析构
2.2.1 构造函数
构造函数(constructor)是与类同名的特殊成员函数,主要用来初始化对象的数据成员。
像上一个例子,初始化的类成员的时候就有点麻烦。
class X{
...
X (...) {//构造函数
...
}
};
构造函数的特点:
- 与类同名
- 没有返回类型
- 可以被重载
- 由系统自动调用,不允许在程序中显示调用
#include <iostream>
using namespace std;
class Student{
private:
string m_name;
int m_age;
int m_no;
public:
Student(const string &name, int age, int no) {
m_name = name;
m_age = age;
m_no = no;
}
/*类内声明*/
void set_name(const string &name);
void set_age(int age);
void set_no(int no);
void eat(const string &food);
void who();
};
/*类外定义*/
void Student::set_name(const string &name){
m_name = name;
}
void Student::set_age(int age) {
m_age = age;
}
void Student::set_no(int no){
m_no = no;
}
void Student::eat(const string &food){
cout << "我今天吃了" << food << endl;
}
void Student::who() {
cout << "我叫: " << m_name << " 今年: " << m_age << " 学号: " << m_no << endl;
}
int main(void) {
Student s1("王钢蛋", 18, 2203);
s1.who();
s1.eat("烙饼");
return 0;
}
2.2.2 缺省构造函数
缺省构造函数也称无参构造函数,但其未必真的没有任何参数,为一个有参构造函数的每个参数都提供一个缺省值,同样可以达到无参构造函数的效果
注意:
- 如果一个类没有定义任何构造函数,那么编译器会为其提供一个缺省构造函数
- 对基本类型的成员变量,不做初始化
- 对类类型的成员变量(成员子对象),将自动调用相应类的无参构造函数来初始化
#include <iostream>
using namespace std;
class A{
public:
int m_i;
A(void){
cout << "A 的无参构造" << endl;
m_i = 123;
}
};
class B{
public:
int m_j; //基本类型成员变量
A m_a; //类类型成员变量(成员子对象)
};
1
int main() {
B b; //调用成员对象m_a的无参构造函数 调用B的缺省构造函数
cout << b.m_j << endl; //未知
cout << b.m_a.m_i << endl; //123
return 0;
}
- 如果一个类定义了构造函数,无论是否有参数,那么编译器都不会再提供缺省构造函数
2.2.3 构造函数的重载
#include <iostream>
using namespace std;
struct param{
int l, w, h, ww;
};
class Desk{
public:
int length, width, height, weight;
Desk(int l, int w, int h, int ww) {
cout << "Desk(int,int,int,int)" << endl;
}
Desk(void) {
cout << "Desk(void)" << endl;
}
Desk(param &p){
cout << "Desk(param &)" << endl;
}
};
int main(void) {
Desk d1(1,2,3,4);
Desk d2;
param pm;
pm.l = 1;
pm.w = 2;
pm.h = 3;
pm.ww = 4;
Desk d3(pm);
return 0;
}
某些重载的构造函数具有特殊的含义:
- 缺省构造函数:按缺省方式构造
- 类型转换构造函数:从不同类型的对象构造
- 拷贝构造函数:从相同类型的对象构造
2.2.4 类型转换构造函数
将其他类型转换为当前类类型需要借助转换构造函数(Conversion constructor),转换构造函数只有一个参数。
#include <iostream>
#include <cstring>
using namespace std;
class Integer {
private:
int m_i;
public:
Integer(void){
cout << "Integer(void)" << endl;
m_i = 3;
}
explicit Integer(int n) {
cout << "Integer(int)" << endl;
m_i = n;
}
explicit Integer(const char *str){
cout << "Integer(const string &)" << endl;
m_i = strlen(str);
}
void print(){
cout << m_i << endl;
}
};
int main(void) {
Integer i;
i.print();
//Integer j = 5; //编译器会找参数为int类型的构造函数
Integer j = Integer(5); //编译器会找参数为int类型的构造函数
j.print();
//Integer k = "hello";
Integer k = Integer("hello");// 这样会更清晰调用的是那个构造函数
k.print();
return 0;
}
explicit关键字,就是告诉编译器需要类型转换时,强制要求写程如下形式:
Integer j = Integer(5);
//Integer j = 5; //error
2.2.5 拷贝构造函数
-
用一个已定义的对象构造同类型的副本对象,将调用该类的拷贝构造函数
class A{ A(const A& that){ //拷贝构造函数 注意参数必须是常引用 ... } }; A a; A b(a);//调用拷贝构造 A c = a;//调用拷贝构造
案例:
#include <iostream> using namespace std; class Data{ public: int m_data; Data(int data = 3){ cout << "Data(int)" << endl; m_data = data; } Data(const Data& that){ //拷贝构造函数 cout << "Data(const A&)" << endl; m_data = that.m_data; } }; int main(void){ Data A1; Data A2(A1); //编译器会调用拷贝构造函数 Data A3 = A1; return 0; }
-
如果一个类没有显示定义拷贝构造函数,那么编译器会为其提供一个缺省拷贝构造函数
- 对基本类型成员变量,按字节复制
- 对类类型成员变量(成员子对象),调用相应类的拷贝构造函数
class User { string m_name; //调用string类的拷贝构造函数 int m_age; //按字节复制 };
案例:
#include <iostream> using namespace std; class A{ public: int m_a; A(int m_a = 0) { //缺省构造函数 cout << "A(int)" << endl; } A(const A& that){ //拷贝构造函数 cout << "A(const A&)" << endl; } }; class B{ public: A m_b; }; int main(void) { B b1; //调用A类中的缺省构造函数 B b2 = b1; //默认调用A类中的拷贝构造函数 return 0; }
-
注意事项
- 拷贝函数的调用时机
- 用已定义对象作为同类型对象的构造实参
- 以对象的形式向函数传递参数
- 从函数中返回对象
- 拷贝构造过程风险高而且效率低,设计时应尽可能避免
- 避免或减少对象的拷贝
- 传递对象形式的参数时,使用引用型参数
- 从函数中返回对象,使用引用函数返回值
- 拷贝函数的调用时机
文章来源:https://blog.csdn.net/qq_36091214/article/details/135187605
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!