C++构造函数
构造函数特点
(1)函数名必须与类名相同,且没有返回值,可以有参数
(2)在定义对象时自动被调用且仅被调用一次
——对象定义语句
——new操作符
(3)作用
——定义对象的各个成员变量并赋初值,设置对象初始状态
——在对象定义之初想实现的任何操作
(4)定义类时没有写构造函数,系统提供一个默认的无参构造函数
——对基本类型的成员变量进行定义,并初始化为随机数
——对类类型成员变量进行定义,并调用相应类型的无参构造函数
如果自己定义构造函数,系统就不提供默认的构造函数
(5)一个类可以有多个构造函数,且构成重载关系
构造函数的分类
无参构造
#include <iostream>
#include <cstring>
using namespace std;
class Human
{
public:
Human()
{
cout << "Human类的构造函数被调用" << endl;
}
void getinfo()
{
cout << "姓名:" << this->m_name << ", 年龄:" << this->m_age << endl;
}
private:
int m_age;
char m_name[256];
};
int main(void)
{
Human h;
h.getinfo();
return 0;
}
运行结果
带参构造函数与缺省构造函数
#include <iostream>
#include <cstring>
using namespace std;
class Human
{
public:
/* 若为构造函数的所有参数都提供默认值,那么这个构造函数可以充当无参构造函数*/
Human(/*Human* this*/int age=0,const char* name="wm")
{
cout << "Human类的构造函数被调用" << endl;
this->m_age=age;
strcpy(this->m_name,name);
}
void getinfo()
{
cout << "姓名:" << this->m_name << ", 年龄:" << this->m_age << endl;
}
private:
int m_age;
char m_name[256];
};
int main(void)
{
#if 0
//默认构造函数的二义性:当我们使用不带参数列表的方式来创建对象时,例如 Human h();
//C++ 解释器会将其误解为函数声明,因为它也符合函数声明的语法,而且具有函数声明的模式。
//这是因为 C++ 编译器在遇到这种情况时,认为这是一个函数声明而不是对象的定义。
Human h();
#endif
Human h(22,"tom");
h.getinfo();
Human h2;
h2.getinfo();
Human h3(22);
h3.getinfo();
return 0;
}
运行结果
拷贝构造函数
1.概念
形如:
class 类名
{
类名 (const 类名& that) {...}
};
2.作用
用一个已定义的对象,来定义其同类型的副本对象,即对象克隆
3.特点
1.调用时机:(1)用已定义对象作为同类型对象的构造实参(2)以对象的形式向函数传递参数(3)从函数中返回对象.(某些拷贝构造过程会被编译器优化)
2.如果一个类没有定义拷贝构造函数,那么编译器会为其提供一个默认拷贝构造函数
对基本类型成员变量进行定义,并赋初值(按字节复制)
对类类型成员变量进行定义,并调用相应类型的拷贝构造函数
3.如果自己定义了拷贝构造函数,编译器将不再提供默认拷贝构造函数,这时所有与成员复制有关的操作,都必须在自定义拷贝构造函数中自己编写代码完成
4.所有编译器定义的构造函数,其访问控制属性均为公有(public)
include <iostream>
using namespace std;
class Human
{
public:
Human(int age=0,const char* name="wr")//构造函数
{
cout << "Human类的缺省构造函数被调用" << endl;
this->m_age=age;
this->m_name=name;
}
Human(const Human& that)
{
cout << "Human类的拷贝构造函数被调用" << endl;
m_age=that.m_age;
m_name=that.m_name;
}
void getinfo()
{
cout << "姓名:" << this->m_name << ", 年龄:" << this->m_age << endl;
}
private:
int m_age;
string m_name;
};
void foo(Human v) {}
int main(void)
{
Human h;
h.getinfo();
Human h2(23,"Tom");
h2.getinfo();
Human h3(h2);//用已定义的对象作为同类型对象的构造实参-->触发拷贝构造函数
h3.getinfo();
foo(h3);//以对象的形式向函数传递参数--->触发拷贝构造函数
Human h4=bar();//从函数中返回对象--->触发拷贝构造函数
return 0;
}
运行结果
拷贝赋值函数
1.概念
形如:
class 类名
{
类名 operator= (const 类名& that) {}
};
2.作用
用一个已定义的对象给同类型的对象赋值,即对象赋值
3.特点
1.如果一个类没有定义拷贝赋值函数,那么编译器会为其提供一个默认拷贝赋值函数
对基本类型成员变量,值传递(按字节复制)
对类类型成员变量,调用相应类型的拷贝赋值函数
2.如果自己定义了拷贝赋值函数,编译器将不再提供默认拷贝赋值函数,
这时所有与成员复制有关的操作,都必须在自定义拷贝赋值函数中自己编写代码完成
include <iostream>
using namespace std;
class Human
{
public:
Human(int age=0,const char* name="wr")//构造函数
{
this->m_age=age;
this->m_name=name;
}
Human& operator=(const Human& that)
{
cout << "Human类的拷贝赋值函数被调用" << endl;
this->m_age=that.m_age;
this->m_name=that.m_name;
return *this;
}
void getinfo()
{
cout << "姓名:" << this->m_name << ", 年龄:" << this->m_age << endl;
}
private:
int m_age;
string m_name;
};
int main(void)
{
Human h1(23,"Tom");
h1.getinfo();
Human h2;
cout << "h2被赋值前---";
h2.getinfo();
h2=h1;
cout << "h2被赋值后---";
h2.getinfo();
return 0;
}
运行结果:
初始化表
1.特点
类中的基本类型成员变量,最好在初始化表中显式指明如何初始化,否则初值不确定。
类中的类类型成员变量,也最好在初始化表中显式指明如何初始化,否则将调动相应类型的无参构造函数。
2.必须在初始化表中显式初始化的情况
1.const成员变量必须在定义的时候初始化
2.引用成员变量必须在定义的时候初始化
3.没有默认构造函数的自定义类型成员变量
#include <iostream>
using namespace std;
class T
{
public:
T(int x,int y)
//若使用编译器的构造函数,或给构造函数提供默认值,可以不在初始化表中显式初始化
{
cout << "T构造函数被执行" << endl;
m_x=x;
m_y=y;
}
void getinfo()
{
cout << "T::m_x=" << m_x << ", T::m_y=" << m_y << endl;
}
private:
int m_x;
int m_y;
};
class Time
{
public:
Time(int year=0,int month=0,int day=0,const int c=0)
: m_year(year),m_month(month),m_day(day)
,m_c(c),ry(m_year),m_a(20,23)
{
cout << "Time构造函数被执行" <<endl;
}
void getinfo()
{
cout << m_year << ":" << m_month << ":" << m_day << endl;
cout << m_c << endl;
cout << ry << endl;
m_a.getinfo();
}
private:
int m_year;
int m_month;
int m_day;
const int m_c;//类的 常量型 成员变量 必须在初始化表中显式初始化
int& ry;//类的 引用型 成员变量 必须在初始化表中显式初始化
T m_a;//没有默认构造函数的自定义类型成员只能在初始化表中初始化
};
int main(void)
{
Time t(2023,12,8,16);
t.getinfo();
return 0;
}
运行结果: