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;

}

结构体与类的区别总结:

相关推荐
m0_6265352014 小时前
快速排序学习 l方法 h方法
开发语言·python
superman超哥15 小时前
Rust String与&str的内部实现差异:所有权与借用的典型案例
开发语言·后端·rust·rust string·string与str·内部实现·所有权与借用
xiaowu08015 小时前
C#调用 C++ DLL 加载地址方式选择
开发语言·c++·c#
非凡ghost15 小时前
MPC-QT视频播放器(基于Qt框架播放器)
开发语言·windows·qt·音视频·软件需求
转基因15 小时前
C++的IO流
开发语言·c++
一碗绿豆汤15 小时前
Java语言概述和开发环境-1
java·开发语言
愈努力俞幸运15 小时前
rust安装
开发语言·后端·rust
天天进步201515 小时前
【Nanobrowser源码分析4】交互篇: 从指令到动作:模拟点击、滚动与输入的底层实现
开发语言·javascript·ecmascript
console.log('npc')15 小时前
vue2中子组件父组件的修改参数
开发语言·前端·javascript
码点15 小时前
【无标题】日文字库Japan.ini
开发语言