40.结构体-构造函数
40.1 知识点
构造函数的基本概念
构造函数是一个特殊的成员函数,用来对结构体对象进行初始化。当我们声明一个结构体变量(对象)时,构造函数会自动被调用。
struct Test
{
// 成员变量
// 成员函数(方法)
// 构造函数,析构函数
};
构造函数的声明
构造函数声明时有一些基本规则:
- 没有返回值。
- 函数名必须和结构体名相同。
- 可以被重载。
- 可以通过两种方式进行赋值:
- 在函数中赋值。
- 利用成员初始化列表来初始化(更高效)。
- 若传入参数和成员变量重名,可以使用
this->成员变量
来表示是成员变量。this
是一个指针,指向当前对象,而不是对象本身,所以要使用->
而不是.
。
以下是一个构造函数的例子:
struct Student
{
int age;
string name;
// 无参构造函数
Student()
{
age = 18;
name = "韬老狮";
}
// 带参数的构造函数
Student(int age, string name) : age(age), name(name)
{
}
Student(int age)
{
this->age = age;
name = "";
}
Student(string name)
{
age = 0;
this->name = name;
}
};
构造函数的使用
构造函数可以通过以下几种方式调用:
1. 栈上分配(不带 new
)
1-1. 使用结构体类型和结构体变量来调用构造函数:
Student s1(10, "哈啊哈");
std::cout << s1.age << std::endl; // 输出:10
std::cout << s1.name << std::endl; // 输出:哈啊哈
1-2. 使用结构体类型和结构体变量初始化列表来调用构造函数:
Student s2{ 20, "嘿嘿嘿" };
std::cout << s2.age << std::endl; // 输出:20
std::cout << s2.name << std::endl; // 输出:嘿嘿嘿
1-3. 使用结构体类型和结构体变量赋值来调用构造函数:
Student s3 = Student(30, "嘻嘻嘻");
std::cout << s3.age << std::endl; // 输出:30
std::cout << s3.name << std::endl; // 输出:嘻嘻嘻
1-4. 使用结构体类型和结构体变量赋值初始化列表来调用构造函数:
Student s4 = Student{ 40, "哈哈哈" };
std::cout << s4.age << std::endl; // 输出:40
std::cout << s4.name << std::endl; // 输出:哈哈哈
1-5. 使用结构体类型和结构体变量赋值直接初始化:
Student s5 = { 50, "哦哦哦" };
std::cout << s5.age << std::endl; // 输出:50
std::cout << s5.name << std::endl; // 输出:哦哦哦
2. 堆上分配(带 new
)
Student* s8 = new Student();
std::cout << s8->age << std::endl; // 输出:18
std::cout << s8->name << std::endl; // 输出:韬老狮
// 释放堆上的内存
delete s8;
s8 = nullptr;
显示定义默认构造函数
如果我们没有为结构体定义任何构造函数,编译器会自动生成一个默认的构造函数。如果定义了其他构造函数(如带参数的构造函数),则默认构造函数不会自动生成,除非我们显式定义它。
注意: 默认构造函数就是一个无参的构造函数。
struct Test
{
int age;
string name;
// 如果声明了其他有参构造的情况下,
// 之后希望使用无参构造函数去声明对象
// 那需要显式声明一个无参构造
// Test()
// {
// age = 0;
// name = "";
// }
// 只要声明了构造函数,那么默认的那个自动生成的无参构造就没用了
// 相当于不会自动生成无参构造
// Test(int age) : age(age) {}
};
Test t;
cout << t.age << std::endl;
cout << t.name << std::endl;
Test* t_ptr = new Test();
cout << t_ptr->age << std::endl;
40.2 知识点代码
Lesson40_结构体_构造函数.cpp
#include <iostream>
using namespace std;
#pragma region 知识点一 构造函数的基本概念
//基本概念:
//构造函数是一个特殊的成员函数
//是用来对结构体对象进行初始化用的
//当我们声明一个结构体变量(对象)时,会自动调用构造函数
//struct Test
//{
// //成员变量
//
// //成员函数(方法)
//
// //构造函数 析构函数
//};
#pragma endregion
#pragma region 知识点二 构造函数的声明
//基本规则
//声明在结构体中
//1.没有返回值
//2.函数名必须和结构体名相同
//3.可以被重载
//4.两种赋值方式
// 4-1:在函数中赋值
// 4-2:利用成员初始化列表来初始化(更高效)
//5.若传入参数和成员变量重名,可以使用 this->成员变量 来表示是成员变量
//this 是一个指针,指向当前对象,而不是对象本身。所以要用->而不是.
struct Student
{
int age;
string name;
//无参构造函数
Student()
{
age = 18;
name = "韬老狮";
}
//age(age), name(name)代表赋值给age和name
Student(int age, string name) : age(age), name(name)
{
}
Student(int age)
{
this->age = age;
name = "";
}
Student(string name)
{
age = 0;
this->name = name;
}
};
#pragma endregion
#pragma region 知识点三 构造函数的使用
//调用构造函数的几种方式
//1.栈上分配-不带new
// 1-1.结构体类型 结构体变量(参数...)
// 1-2.结构体类型 结构体变量{参数...}
// 1-3.结构体类型 结构体变量 = 结构体类型(参数...);
// 1-4.结构体类型 结构体变量 = 结构体类型{参数...};
// 1-5.结构体类型 结构体变量 = {参数...};
//2.堆上分配-带new
// 结构体类型 结构体变量 = new 结构体类型(参数);
//结构体还有两个默认的构造函数
//1.传入 const 左值引用的构造
// 主要作用:避免不必要的复制,允许使用已有的对象用来初始化成员
// 一般用来处理复制另一个对象的数据
//2.传入 右值引用的构造
// 主要作用:接收将要被移动的临时对象或其他右值,可以提高性能
#pragma endregion
#pragma region 知识点四 显示定义默认构造函数
//如果我们没有为结构体定义任何构造函数
//编译器会生成一个默认的构造函数
//如果定义了其他构造函数(如带参数的构造函数)
//则默认构造函数不会被自动生成
//除非我们显式定义它
//注意:默认构造函数就是一个无参的构造函数
struct Test
{
int age;
string name;
////如果声明了其他有参构造的情况下
////之后希望使用无参构造函数去声明对象
////那需要显示的声明一个无参构造
//Test()
//{
// age = 0;
// name = "";
//}
////只要声明了构造函数 那么默认的那个自动生成的无参构造就没用了
////相当于不会自动生成无参构造
//Test(int age) : age(age) {}
};
#pragma endregion
int main()
{
std::cout << "构造函数\n";
#pragma region 知识点三 构造函数的使用
// 调用构造函数的几种方式
// 1. 栈上分配-不带 new
// 1-1. 结构体类型 结构体变量(参数...)
Student s1(10, "哈啊哈");
std::cout << s1.age << std::endl; // 输出:10
std::cout << s1.name << std::endl; // 输出:哈啊哈
// 1-2. 结构体类型 结构体变量{参数...}
Student s2{ 20, "嘿嘿嘿" };
std::cout << s2.age << std::endl; // 输出:20
std::cout << s2.name << std::endl; // 输出:嘿嘿嘿
// 1-3. 结构体类型 结构体变量 = 结构体类型(参数...);
Student s3 = Student(30, "嘻嘻嘻");
std::cout << s3.age << std::endl; // 输出:30
std::cout << s3.name << std::endl; // 输出:嘻嘻嘻
// 1-4. 结构体类型 结构体变量 = 结构体类型{参数...};
Student s4 = Student{ 40, "哈哈哈" };
std::cout << s4.age << std::endl; // 输出:40
std::cout << s4.name << std::endl; // 输出:哈哈哈
// 1-5. 结构体类型 结构体变量 = {参数...};
Student s5 = { 50, "哦哦哦" };
std::cout << s5.age << std::endl; // 输出:50
std::cout << s5.name << std::endl; // 输出:哦哦哦
// 调用只带有一个 int 参数的构造函数
Student s6(60);
std::cout << s6.age << std::endl; // 输出:60
std::cout << s6.name << std::endl; // 输出:
// 调用只带有一个 string 参数的构造函数
Student s7("啦啦啦");
std::cout << s7.age << std::endl; // 输出:0
std::cout << s7.name << std::endl; // 输出:啦啦啦
// 2. 堆上分配-带 new
// 结构体类型 结构体变量 = new 结构体类型(参数);
Student* s8 = new Student();
std::cout << s8->age << std::endl; // 输出:18
std::cout << s8->name << std::endl; // 输出:韬老狮
// 释放堆上的内存
delete s8;
s8 = nullptr;
#pragma endregion
#pragma region 知识点四 显示定义默认构造函数
Test t;
cout << t.age << endl;
cout << t.name << endl;
Test* t_ptr = new Test();
cout << t_ptr->age << endl;
#pragma endregion
}
40.3 练习题
使用结构体描述矩形的信息,长,宽;创建一个矩形,对其长宽进行初始化,并打印矩形的长、宽、面积、周长等信息。
struct Rect
{
//长 宽 面积 周长相关成员变量
float w;
float h;
float area;
float perimeter;
Rect(float w, float h)
{
this->w = w;
this->h = h;
area = w * h;
perimeter = 2 * (w + h);
}
void coutInfo()
{
cout << "该矩形宽为" << w << "高为" << h << "面积为" << area
<< "周长为" << perimeter << endl;
}
};
Rect r = Rect(10, 5);
r.coutInfo(); //该矩形宽为10高为5面积为50周长为30
使用结构体描述玩家信息,玩家名字,玩家职业
请用户输入玩家姓名,选择玩家职业,最后打印玩家的攻击信息
职业:
战士(技能:冲锋)
猎人(技能:假死)
法师(技能:奥术冲击)
打印结果:猎人韬老狮释放了假死
enum E_Occupation
{
Warrior, //战士
Hunter, //猎人
Master //法师
};
struct PlayerInfo
{
string name;
E_Occupation occupation;
PlayerInfo(string name, E_Occupation occupation)
{
this->name = name;
this->occupation = occupation;
}
//攻击方法
void Atk()
{
string o = "";
string skill = "";
switch (occupation)
{
case Warrior:
o = "战士";
skill = "冲锋";
break;
case Hunter:
o = "猎人";
skill = "假死";
break;
case Master:
o = "法师";
skill = "奥术冲击";
break;
default:
break;
}
cout << o + name << "释放了" << skill << endl;
}
};
try
{
cout << "请输入玩家姓名" << endl;
string strName;
cin >> strName;
cout << "请输入玩家职业(0战士 1猎人 2法师)" << endl;
string strO;
cin >> strO;
E_Occupation o = static_cast<E_Occupation>(stoi(strO));
PlayerInfo info = PlayerInfo(strName, o);
info.Atk();
}
catch (const std::exception&)
{
cout << "请按规范输入内容" << endl;
}
40.4 练习题代码
Lesson40_练习题.cpp
#include <iostream>
#include <string>
using namespace std;
#pragma region 练习题一
//使用结构体描述矩形的信息,长,宽;创建一个矩形,对其长宽进行初始化,
//并打印矩形的长、宽、面积、周长等信息。
struct Rect
{
//长 宽 面积 周长相关成员变量
float w;
float h;
float area;
float perimeter;
Rect(float w, float h)
{
this->w = w;
this->h = h;
area = w * h;
perimeter = 2 * (w + h);
}
void coutInfo()
{
cout << "该矩形宽为" << w << "高为" << h << "面积为" << area
<< "周长为" << perimeter << endl;
}
};
#pragma endregion
#pragma region 练习题二
//使用结构体描述玩家信息,玩家名字,玩家职业
//请用户输入玩家姓名,选择玩家职业,最后打印玩家的攻击信息
//职业:
//战士(技能:冲锋)
//猎人(技能:假死)
//法师(技能:奥术冲击)
//
//打印结果:猎人韬老狮释放了假死
enum E_Occupation
{
Warrior,//战士
Hunter,//猎人
Master,//法师
};
struct PlayerInfo
{
string name;
E_Occupation occupation;
PlayerInfo(string name, E_Occupation occupation)
{
this->name = name;
this->occupation = occupation;
}
//攻击方法
void Atk()
{
string o = "";
string skill = "";
switch (occupation)
{
case Warrior:
o = "战士";
skill = "冲锋";
break;
case Hunter:
o = "猎人";
skill = "假死";
break;
case Master:
o = "法师";
skill = "奥术冲击";
break;
default:
break;
}
cout << o + name << "释放了" << skill << endl;
}
};
#pragma endregion
int main()
{
std::cout << "构造函数 练习题\n";
#pragma region 练习题一
Rect r = Rect(10, 5);
r.coutInfo();//该矩形宽为10高为5面积为50周长为30
#pragma endregion
#pragma region 练习题二
try
{
cout << "请输入玩家姓名" << endl;
string strName;
cin >> strName;
cout << "请输入玩家职业(0战士 1猎人 2法师)" << endl;
string strO;
cin >> strO;
E_Occupation o = static_cast<E_Occupation>(stoi(strO));
PlayerInfo info = PlayerInfo(strName, o);
info.Atk();
}
catch (const std::exception&)
{
cout << "请按规范输入内容" << endl;
}
#pragma endregion
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com