C++基础教程8 结构体与类

C++ 结构体详解

1. 结构体的概念

在C++中,结构体(struct 是一种用户自定义的数据类型,可以将不同类型的变量组合在一起。每个变量叫做结构体的成员,可以是不同数据类型的组合。结构体允许你将多个数据项作为一个单元进行处理,方便存储和操作。

结构体的定义是为了使数据更加有组织,尤其是在需要同时处理多个相关数据时。比如,我们可以用结构体来表示一个学生,学生包含姓名、年龄、成绩等信息。结构体使得管理这些信息更加清晰。

2. 结构体的定义与声明

结构体的定义可以通过struct关键字来完成,格式如下:

struct 结构体名 {
    数据类型 成员名1;
    数据类型 成员名2;
    数据类型 成员名3;
    // ...
};

示例:定义一个简单的结构体

#include <iostream>
using namespace std;

// 定义一个表示学生的结构体
struct Student {
    string name;    // 姓名
    int age;        // 年龄
    float grade;    // 成绩
};

int main() {
    // 创建一个Student类型的变量
    Student student1;
    
    // 为结构体成员赋值
    student1.name = "Tom";
    student1.age = 20;
    student1.grade = 85.5;

    // 输出结构体成员
    cout << "Name: " << student1.name << endl;
    cout << "Age: " << student1.age << endl;
    cout << "Grade: " << student1.grade << endl;

    return 0;
}

解释:

  1. 定义结构体:我们用struct Student定义了一个结构体类型Student,其中包含三个成员:name(字符串类型)、age(整数类型)和grade(浮点数类型)。

  2. 创建结构体变量:在main函数中,我们通过Student student1声明了一个Student类型的结构体变量。

  3. 访问成员:使用.操作符来访问和修改结构体变量的成员。

输出:

Name: Tom
Age: 20
Grade: 85.5

3. 结构体初始化

3.1 初始化结构体变量

C++允许在声明结构体变量时直接进行初始化,这样可以在创建结构体实例时就赋予它初始值。

#include <iostream>
using namespace std;

// 定义一个结构体
struct Point {
    int x;
    int y;
};

int main() {
    // 通过初始化列表直接初始化结构体变量
    Point p1 = {10, 20};

    cout << "x: " << p1.x << ", y: " << p1.y << endl;

    return 0;
}

3.2 使用指定初始化

在C++11及以后的版本中,可以使用指定初始化来清晰地初始化结构体成员。

#include <iostream>
using namespace std;

// 定义一个结构体
struct Point {
    int x;
    int y;
};

int main() {
    // 使用指定初始化
    Point p1 = {.x = 10, .y = 20};

    cout << "x: " << p1.x << ", y: " << p1.y << endl;

    return 0;
}

3.3 默认初始化

如果在定义结构体变量时没有提供初始化值,结构体成员将会被默认初始化:

  • 如果结构体成员是基本数据类型(如intfloat等),则它们的值是未定义的,可能包含垃圾值。

  • 如果结构体成员是类类型(如std::string),则会调用其默认构造函数进行初始化。

示例:未初始化的结构体

#include <iostream>
using namespace std;

struct Student {
    string name;
    int age;
    float grade;
};

int main() {
    Student student1;  // 没有初始化

    cout << "Name: " << student1.name << endl;   // 未定义,可能为垃圾值
    cout << "Age: " << student1.age << endl;     // 未定义,可能为垃圾值
    cout << "Grade: " << student1.grade << endl; // 未定义,可能为垃圾值

    return 0;
}

4. 结构体的传递

4.1 传值调用

当将结构体作为参数传递给函数时,默认是通过值传递的。这样会创建结构体的副本,修改副本不会影响原结构体。

#include <iostream>
using namespace std;

struct Student {
    string name;
    int age;
    float grade;
};

void printStudent(Student student) {
    // 修改副本
    student.name = "Changed Name";
    cout << "Student Name: " << student.name << endl;
}

int main() {
    Student student1 = {"Tom", 20, 85.5};
    printStudent(student1);  // 传递副本
    cout << "Original Name: " << student1.name << endl;  // 原始结构体未改变
    return 0;
}

4.2 传引用调用

为了避免复制结构体带来的开销,或者希望函数内修改结构体内容时影响原结构体,可以通过引用传递的方式来传递结构体。

#include <iostream>
using namespace std;

struct Student {
    string name;
    int age;
    float grade;
};

void updateStudent(Student &student) {
    student.name = "Updated Name";  // 修改原始结构体
}

int main() {
    Student student1 = {"Tom", 20, 85.5};
    updateStudent(student1);  // 传递引用
    cout << "Updated Name: " << student1.name << endl;  // 原始结构体已改变
    return 0;
}

4.3 传指针调用

还可以通过指针传递结构体,这样可以避免复制结构体并且能够修改原始数据。传递指针需要使用*来解引用。

#include <iostream>
using namespace std;

struct Student {
    string name;
    int age;
    float grade;
};

void updateStudent(Student *student) {
    student->name = "Updated by Pointer";  // 使用指针修改
}

int main() {
    Student student1 = {"Tom", 20, 85.5};
    updateStudent(&student1);  // 传递指针
    cout << "Updated Name: " << student1.name << endl;  // 原始结构体已改变
    return 0;
}

5. 结构体数组

C++中可以定义结构体数组,这样可以存储多个相同类型的结构体。结构体数组可以用来表示同类事物的集合,比如多个学生的信息。

示例:学生信息数组

#include <iostream>
using namespace std;

struct Student {
    string name;
    int age;
    float grade;
};

int main() {
    // 创建一个包含3个学生的结构体数组
    Student students[3] = {
        {"Tom", 20, 85.5},
        {"Alice", 22, 90.0},
        {"Bob", 19, 88.5}
    };

    // 输出所有学生信息
    for (int i = 0; i < 3; i++) {
        cout << "Name: " << students[i].name << ", Age: " << students[i].age
             << ", Grade: " << students[i].grade << endl;
    }

    return 0;
}

输出:

Name: Tom, Age: 20, Grade: 85.5
Name: Alice, Age: 22, Grade: 90
Name: Bob, Age: 19, Grade: 88.5

6. 结构体与指针

结构体与指针的结合使用是C++中的重要概念,可以通过指针高效地处理动态内存分配的结构体。

示例:结构体指针

#include <iostream>
using namespace std;

struct Student {
    string name;
    int age;
    float grade;
};

int main() {
    // 动态创建一个结构体
    Student *studentPtr = new Student;

    // 通过指针访问和修改结构体成员
    studentPtr->name = "Tom";
    studentPtr->age = 20;
    studentPtr->grade = 85.5;

    cout << "Name: " << studentPtr->name << endl;
    cout << "Age: " << studentPtr->age << endl;
    cout << "Grade: " << studentPtr->grade << endl;

    // 删除动态分配的内存
    delete studentPtr;

    return 0;
}

解析:

1

. 使用new动态创建结构体变量,返回的是结构体的指针。 2. 使用->操作符访问结构体指针的成员。 3. 使用delete释放动态分配的内存。

7. 结构体的高级应用

7.1 结构体作为函数返回值

C++支持结构体作为函数的返回值,这使得可以通过函数返回结构体数据。

#include <iostream>
using namespace std;

struct Point {
    int x;
    int y;
};

Point createPoint(int x, int y) {
    Point p;
    p.x = x;
    p.y = y;
    return p;
}

int main() {
    Point p = createPoint(10, 20);
    cout << "Point x: " << p.x << ", y: " << p.y << endl;
    return 0;
}

7.2 结构体与类的关系

在C++中,structclass有很多相似之处。唯一的区别是:

  • struct的成员默认是公共的(public)

  • class的成员默认是私有的(private)

#include <iostream>
using namespace std;

struct MyStruct {
    int x;  // public by default
};

class MyClass {
private:
    int x;  // private by default
public:
    void setX(int val) {
        x = val;
    }
    int getX() {
        return x;
    }
};

int main() {
    MyStruct s;
    s.x = 10;  // 可以直接访问

    MyClass c;
    c.setX(20);  // 通过公有函数访问

    cout << "MyStruct x: " << s.x << endl;
    cout << "MyClass x: " << c.getX() << endl;

    return 0;
}

类详解(看不懂就不看了 结构体学会就行)

在C++中,类(class)是面向对象编程(OOP)的核心概念之一。它是一种自定义的数据类型,用于描述一组具有相同特征和行为的对象。类是对象的蓝图或模板,它包含了对象的属性(数据成员)和行为(成员函数)。通过类,我们可以将现实世界的实体转化为代码中的对象,使得代码更加模块化、可扩展且易于维护。

1. 类的定义与使用

1.1 类的基本结构

在C++中,类通过class关键字定义,类的定义包括以下几个部分:

  • 类名:类的名称,通常遵循大驼峰命名法(如PersonCar等)。

  • 成员变量(属性):类的属性,用于存储对象的状态,通常是数据类型。

  • 成员函数(行为):类的行为,用于定义对象能够执行的操作。

类的基本结构如下:

class 类名 {
public:
    // 数据成员
    数据类型 成员名1;
    数据类型 成员名2;
    
    // 构造函数
    类名();

    // 成员函数
    void 成员函数1();
    void 成员函数2();
};

示例:定义一个简单的Person

#include <iostream>
using namespace std;

class Person {
public:
    // 数据成员
    string name;
    int age;

    // 构造函数
    Person(string n, int a) {
        name = n;
        age = a;
    }

    // 成员函数
    void introduce() {
        cout << "Hello, my name is " << name << " and I am " << age << " years old." << endl;
    }
};

int main() {
    // 创建对象并初始化
    Person person1("Alice", 30);
    person1.introduce();

    return 0;
}

解释:

  1. 类的定义Person类包含两个数据成员:name(字符串类型)和age(整数类型),以及一个成员函数introduce,用于输出对象的介绍。

  2. 构造函数Person类有一个带参数的构造函数,用于初始化对象的属性。

  3. 对象创建:在main函数中,创建了一个Person类的对象person1,并通过构造函数初始化其nameage

输出:

Hello, my name is Alice and I am 30 years old.

2. 构造函数与析构函数

2.1 构造函数

构造函数是类的一种特殊成员函数,它在创建对象时自动调用,用于初始化对象的状态。构造函数的名称必须与类名相同,并且没有返回类型。

构造函数的类型有:

  • 默认构造函数:不带任何参数的构造函数。

  • 带参数构造函数:可以带参数的构造函数,用于在创建对象时传入初始值。

  • 拷贝构造函数:用于通过另一个对象初始化当前对象。

示例:构造函数
#include <iostream>
using namespace std;

class Rectangle {
public:
    int length;
    int width;

    // 默认构造函数
    Rectangle() {
        length = 5;
        width = 3;
    }

    // 带参数构造函数
    Rectangle(int l, int w) {
        length = l;
        width = w;
    }

    void displayArea() {
        cout << "Area: " << length * width << endl;
    }
};

int main() {
    Rectangle rect1;  // 调用默认构造函数
    Rectangle rect2(10, 6);  // 调用带参数构造函数

    rect1.displayArea();  // 输出面积:15
    rect2.displayArea();  // 输出面积:60

    return 0;
}

2.2 析构函数

析构函数是类的一种特殊成员函数,用于在对象生命周期结束时进行资源清理。析构函数的名称与类名相同,但前面加一个波浪号~,没有参数,也没有返回值。C++会在对象销毁时自动调用析构函数。

class MyClass {
public:
    MyClass() {
        cout << "Constructor called" << endl;
    }

    ~MyClass() {
        cout << "Destructor called" << endl;
    }
};

int main() {
    MyClass obj;  // 创建对象时调用构造函数
    return 0;  // 程序结束时,调用析构函数
}

输出:

Constructor called
Destructor called

3. 类的成员函数

类的成员函数定义了类的行为,成员函数可以访问和修改类的成员变量。

3.1 成员函数的定义与调用

成员函数可以在类内部定义,也可以在类外部定义。成员函数通过对象来调用。

示例:类的成员函数
#include <iostream>
using namespace std;

class Circle {
private:
    float radius;

public:
    // 构造函数
    Circle(float r) {
        radius = r;
    }

    // 成员函数
    float getArea() {
        return 3.14 * radius * radius;
    }

    void setRadius(float r) {
        radius = r;
    }
};

int main() {
    Circle circle1(5);  // 创建对象并初始化半径
    cout << "Area: " << circle1.getArea() << endl;  // 调用成员函数
    circle1.setRadius(10);  // 设置新的半径
    cout << "Updated Area: " << circle1.getArea() << endl;  // 调用成员函数

    return 0;
}

3.2 常成员函数

常成员函数(const成员函数)是指不会修改类成员变量的成员函数。常成员函数的声明中使用const关键字。

class Student {
private:
    string name;

public:
    Student(string n) : name(n) {}

    // 常成员函数
    void printName() const {
        cout << "Name: " << name << endl;
    }
};

4. 访问控制:publicprivateprotected

类中的数据成员和成员函数的访问控制由访问控制符来控制,常用的访问控制符有:

  • public:公共成员,任何函数或对象都可以访问。

  • private:私有成员,只有类的成员函数才能访问,外部无法直接访问。

  • protected:保护成员,类本身及其派生类可以访问,外部无法直接访问。

示例:访问控制

class Account {
private:
    double balance;

public:
    Account(double initial_balance) {
        balance = initial_balance;
    }

    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
        }
    }

    double getBalance() const {
        return balance;
    }
};

int main() {
    Account acc(1000);
    acc.deposit(500);
    acc.withdraw(200);

    cout << "Account balance: " << acc.getBalance() << endl;  // 1300
    return 0;
}

5. 类的继承与多态(简要)

5.1 继承

继承是面向对象的一个重要特性,它允许我们在已有的类基础上创建新的类,新的类称为派生类(derived class),继承自基类(base class)的属性和方法。

class Animal {
public:
    void eat() {
        cout << "Eating..." << endl;
    }
};

class Dog : public Animal {
public:
    void bark() {
        cout << "Barking..." << endl;
    }
};

int main() {
    Dog dog;
    dog.eat();  // 从Animal继承的成员
    dog.bark();  // Dog类自己的成员
    return 0;
}

5.2 多态

多态是指相同的操作作用于不同的对象时,产生不同的结果。它通常通过虚函数实现。虚函数允许派生类重写基类中的方法,从而在运行时动态决定调用哪个函数。

class Shape {
public:
    virtual void draw() {
        cout << "Drawing a shape" << endl;
    }
};

class Circle : public Shape {
public:
    void draw() override {
        cout << "Drawing a circle" << endl;
    }
};

int main() {
    Shape* shape = new Circle();
    shape->draw();  // 输出:Drawing a
    circle delete shape; 
    return 0; 
}

练习

练习题:学生信息管理

题目描述:

请设计一个结构体来管理学生的基本信息,要求实现以下功能:

  1. 定义一个Student结构体,其中包含以下数据成员:

    • name:学生姓名,字符串类型。

    • age:学生年龄,整数类型。

    • score:学生成绩,浮点数类型。

  2. 创建一个Student类型的数组,用于存储多名学生的基本信息。

  3. 通过键盘输入学生的姓名、年龄和成绩,将信息存储到结构体数组中。

  4. 显示所有学生的基本信息,包括姓名、年龄和成绩。

  5. 计算并输出所有学生的平均成绩。

输入输出示例:

输入:

请输入学生人数: 2
请输入学生姓名: Alice
请输入学生年龄: 20
请输入学生成绩: 90.5
请输入学生姓名: Bob
请输入学生年龄: 22
请输入学生成绩: 85.0

输出:

学生信息:
姓名: Alice, 年龄: 20, 成绩: 90.5
姓名: Bob, 年龄: 22, 成绩: 85.0

平均成绩: 87.75
提示:
  • 可以使用struct来定义学生信息结构体。

  • 使用数组存储多个学生的信息。

  • 使用循环输入学生信息并输出。


题解:

我们可以按照以下步骤来实现这个练习:

  1. 定义结构体:首先,定义一个Student结构体,包含nameagescore三个成员。

  2. 输入学生信息:通过循环输入多个学生的信息,并将这些信息存储到一个Student类型的数组中。

  3. 输出学生信息:遍历结构体数组,输出每个学生的信息。

  4. 计算平均成绩:遍历结构体数组,计算所有学生成绩的平均值并输出。

代码实现:
#include <iostream>
#include <string>
using namespace std;

// 定义学生结构体
struct Student {
    string name;  // 学生姓名
    int age;      // 学生年龄
    float score;  // 学生成绩
};

int main() {
    int n;

    // 输入学生人数
    cout << "请输入学生人数: ";
    cin >> n;

    // 创建结构体数组
    Student students[n];

    // 输入学生信息
    for (int i = 0; i < n; i++) {
        cout << "请输入学生姓名: ";
        cin >> students[i].name;
        cout << "请输入学生年龄: ";
        cin >> students[i].age;
        cout << "请输入学生成绩: ";
        cin >> students[i].score;
    }

    // 输出所有学生信息
    cout << "\n学生信息:" << endl;
    for (int i = 0; i < n; i++) {
        cout << "姓名: " << students[i].name 
             << ", 年龄: " << students[i].age 
             << ", 成绩: " << students[i].score << endl;
    }

    // 计算平均成绩
    float totalScore = 0;
    for (int i = 0; i < n; i++) {
        totalScore += students[i].score;
    }
    float averageScore = totalScore / n;

    // 输出平均成绩
    cout << "\n平均成绩: " << averageScore << endl;

    return 0;
}
代码说明:
  1. 结构体定义:首先定义了一个Student结构体,包含nameagescore成员,分别表示学生的姓名、年龄和成绩。

  2. 数组存储学生信息:通过输入学生人数,创建一个Student类型的数组,数组大小为n,用来存储每个学生的信息。

  3. 输入学生信息:使用for循环输入每个学生的姓名、年龄和成绩,存储在结构体数组中。

  4. 输出学生信息:使用for循环遍历结构体数组,输出每个学生的基本信息。

  5. 计算平均成绩:通过遍历数组,累加所有学生的成绩,最后计算平均成绩并输出。

示例执行过程:
请输入学生人数: 2
请输入学生姓名: Alice
请输入学生年龄: 20
请输入学生成绩: 90.5
请输入学生姓名: Bob
请输入学生年龄: 22
请输入学生成绩: 85.0

学生信息:
姓名: Alice, 年龄: 20, 成绩: 90.5
姓名: Bob, 年龄: 22, 成绩: 85.0

平均成绩: 87.75
练习重点:
  • 结构体的定义和使用。

  • 如何通过结构体数组存储多个学生的信息。

  • 如何遍历结构体数组并进行输出。

  • 如何计算平均成绩。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值