C/C++——结构体(Struct)

目录

[1.C++ 结构体的基础:存储数据(兼容 C 语言)](#1.C++ 结构体的基础:存储数据(兼容 C 语言))

[1.1定义与使用(C 风格)](#1.1定义与使用(C 风格))

1.2结构体数组

[2.C++ 结构体的扩展:面向对象特性(区别于 C 语言)](#2.C++ 结构体的扩展:面向对象特性(区别于 C 语言))

2.1包含成员函数(方法)

2.2构造函数与析构函数

2.3访问权限控制(public/private/protected)

3.4继承与多态


结构体(Struct)本质上和类(class)几乎一致。

C++ 的结构体是从 C 语言的结构体扩展而来的,它不仅能存储数据(C 语言的特性),还能包含成员函数、构造函数、继承、多态等面向对象特性,仅在默认访问权限和继承权限上有区别

1.C++ 结构体的基础:存储数据(兼容 C 语言)

C 语言的结构体只能包含数据成员(字段),用于将不同类型的数据封装成一个整体,C++ 完全兼容这一特性,这是结构体最基础的用法。

1.1定义与使用(C 风格)

#include <iostream>

#include <cstring>

using namespace std;

// 定义结构体:封装不同类型的数据

struct Student {

// 数据成员(字段)

char name[20]; // 姓名

int age; // 年龄

float score; // 成绩

};

int main() {

// 1. 创建结构体实例(栈上)

Student s1;

// 赋值:通过.访问成员

strcpy(s1.name, "张三"); // C风格字符串赋值

s1.age = 20;

s1.score = 90.5f;

// 2. 直接初始化(C++11后支持大括号初始化)

Student s2 = {"李四", 21, 88.0f};

// 3. 指针方式创建(堆上)

Student* s3 = new Student;

// 指针访问成员:->

strcpy(s3->name, "王五");

s3->age = 19;

s3->score = 95.0f;

// 输出

cout << "姓名:" << s1.name << ",年龄:" << s1.age << ",成绩:" << s1.score << endl;

cout << "姓名:" << s2.name << ",年龄:" << s2.age << ",成绩:" << s2.score << endl;

cout << "姓名:" << s3->name << ",年龄:" << s3->age << ",成绩:" << s3->score << endl;

// 释放堆内存

delete s3;

s3 = nullptr;

return 0;

}

1.2结构体数组

结构体常用来创建数组,存储一组同类型的结构化数据:

// 定义结构体数组

Student students[3] = {

{"张三", 20, 90.5f},

{"李四", 21, 88.0f},

{"王五", 19, 95.0f}

};

// 遍历数组

for (int i = 0; i < 3; i++) {

cout << "第" << i+1 << "个学生:" << students[i].name << ",年龄:" << students[i].age << endl;

}

2.C++ 结构体的扩展:面向对象特性(区别于 C 语言)

2.1包含成员函数(方法)

结构体中可以定义成员函数,用于操作结构体的数据成员,实现行为封装。

struct Student {

char name[20];

int age;

float score;

// 成员函数:显示学生信息

void ShowInfo() {

cout << "姓名:" << name << ",年龄:" << age << ",成绩:" << score << endl;

}

// 成员函数:修改成绩

void SetScore(float newScore) {

score = newScore;

}

};

// 使用

int main() {

Student s = {"张三", 20, 90.5f};

s.ShowInfo(); // 调用成员函数

s.SetScore(92.0f);

s.ShowInfo(); // 输出修改后的成绩

return 0;

}

2.2构造函数与析构函数

结构体可以定义构造函数 (用于初始化实例)和析构函数(用于清理资源),解决 C 风格结构体初始化繁琐的问题。

#include <string> // 使用C++的string类(更安全)

using namespace std;

struct Student {

// 用C++的string替代char数组,避免内存越界

string name;

int age;

float score;

// 无参构造函数(默认构造函数)

Student() {

name = "未知";

age = 0;

score = 0.0f;

cout << "无参构造函数被调用" << endl;

}

// 有参构造函数(重载)

Student(string n, int a, float s) : name(n), age(a), score(s) {

cout << "有参构造函数被调用" << endl;

}

// 析构函数(清理资源,如堆内存、文件句柄等)

~Student() {

cout << "析构函数被调用:" << name << endl;

}

// 成员函数

void ShowInfo() {

cout << "姓名:" << name << ",年龄:" << age << ",成绩:" << score << endl;

}

};

int main() {

// 调用有参构造函数

Student s1("张三", 20, 90.5f);

s1.ShowInfo();

// 调用无参构造函数

Student s2;

s2.ShowInfo();

// 堆上创建,调用有参构造函数

Student* s3 = new Student("李四", 21, 88.0f);

s3->ShowInfo();

delete s3; // 手动释放,调用析构函数

return 0;

}

1.构造函数名与结构体名相同,无返回值,可以重载(多个参数不同的构造函数)。

2.如果没有手动定义构造函数,编译器会自动生成默认的无参构造函数。

2.3访问权限控制(public/private/protected

C++ 结构体支持访问权限修饰符,用于控制成员的访问范围(结构体成员默认是public,类成员默认是private,这是和class的第一个区别)。

struct Student {

private: // 私有成员:只能在结构体内部访问

float score; // 成绩私有化,通过成员函数操作

public: // 公共成员:外部可以访问(默认权限)

string name;

int age;

// 构造函数

Student(string n, int a, float s) : name(n), age(a), score(s) {}

// 公共方法:获取私有成员(封装)

float GetScore() {

return score;

}

// 公共方法:修改私有成员(可以添加校验逻辑)

bool SetScore(float newScore) {

if (newScore >= 0 && newScore <= 100) {

score = newScore;

return true;

}

cout << "成绩无效!" << endl;

return false;

}

};

int main() {

Student s("张三", 20, 90.5f);

cout << s.name << "的成绩:" << s.GetScore() << endl;

// s.score = 105; // 错误:私有成员,外部无法直接访问

s.SetScore(105); // 校验失败,输出提示

s.SetScore(95.0f); // 校验成功

cout << s.name << "的新成绩:" << s.GetScore() << endl;

return 0;

}

2.4继承与多态

结构体可以继承其他结构体 / 类,也可以实现多态(通过虚函数),这是和class的第二个区别:结构体的默认继承权限是public,而类是private

继承:

// 基类:Person

struct Person {

string name;

int age;

Person(string n, int a) : name(n), age(a) {}

void ShowBaseInfo() {

cout << "姓名:" << name << ",年龄:" << age << endl;

}

};

// 派生类:Student 继承 Person(默认public继承)

struct Student : Person {

float score;

// 派生类构造函数:调用基类构造函数

Student(string n, int a, float s) : Person(n, a), score(s) {}

void ShowAllInfo() {

ShowBaseInfo(); // 调用基类方法

cout << "成绩:" << score << endl;

}

};

int main() {

Student s("张三", 20, 90.5f);

s.ShowAllInfo();

// 可以直接访问基类的public成员(因为是public继承)

cout << s.name << endl;

return 0;

}

Person(string n, int a) : name(n), age(a) {}C++ 中的构造函数初始化列表语法,

name(n)表示将构造函数的参数n赋值给Person的成员变量name,完成name的初始化。

age(a)表示将构造函数的参数a赋值给Person的成员变量age,完成age的初始化。

一般写成下面的形式,但不推荐这种写法,因为多了一次默认初始化的开销,效率更低;对于const成员、引用成员,这种写法直接报错 (因为const和引用必须在初始化时赋值,不能后续赋值)。

struct Person {

string name;

int age;

// 函数体中赋值

Person(string n, int a) {

name = n; // 先默认初始化name,再赋值

age = a; // 先默认初始化age,再赋值

}

};

多态:

struct Person {

string name;

int age;

Person(string n, int a) : name(n), age(a) {}

// 虚函数:允许派生类重写

virtual void ShowInfo() {

cout << "姓名:" << name << ",年龄:" << age << endl;

}

// 虚析构函数:确保派生类析构函数被调用

virtual ~Person() {}

};

struct Student : Person {

float score;

Student(string n, int a, float s) : Person(n, a), score(s) {}

// 重写基类的虚函数

void ShowInfo() override {

cout << "姓名:" << name << ",年龄:" << age << ",成绩:" << score << endl;

}

};

int main() {

// 基类指针指向派生类对象(多态)

Person* p = new Student("张三", 20, 90.5f);

p->ShowInfo(); // 调用Student的ShowInfo(多态效果)

delete p;

return 0;

}

结构体与类的区别总结:

相关推荐
Lucis__2 小时前
红黑树实现—规则&约束的平衡之道
数据结构·c++·算法·红黑树
大佬,救命!!!2 小时前
python对应sql操作
开发语言·python·sql·学习笔记·学习方法
IT方大同2 小时前
C语言选择控制结构
c语言·开发语言
名誉寒冰2 小时前
深入理解fd_set:从基础到实战应用(Linux/C++)
java·linux·c++
A24207349302 小时前
js模糊搜索
开发语言·javascript·ecmascript
智者知已应修善业2 小时前
【字符串提取3个整数求和】2024-2-11
c语言·c++·经验分享·笔记·算法
Darkershadow2 小时前
Python学习之使用pycharts
开发语言·python
晚秋大魔王2 小时前
C语言-宏的基础、进阶、高级、内置宏的用法
c语言·开发语言·
moxiaoran57532 小时前
Go语言的递归函数
开发语言·后端·golang