40.结构体构造函数

40.结构体-构造函数


40.1 知识点

构造函数的基本概念

构造函数是一个特殊的成员函数,用来对结构体对象进行初始化。当我们声明一个结构体变量(对象)时,构造函数会自动被调用。

struct Test
{
    // 成员变量

    // 成员函数(方法)

    // 构造函数,析构函数
};

构造函数的声明

构造函数声明时有一些基本规则:

  • 没有返回值。
  • 函数名必须和结构体名相同。
  • 可以被重载。
  • 可以通过两种方式进行赋值:
    1. 在函数中赋值。
    2. 利用成员初始化列表来初始化(更高效)。
  • 若传入参数和成员变量重名,可以使用 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

×

喜欢就点赞,疼爱就打赏