C++基础(04)—— 结构体及typedef

本文详细介绍了C++中结构体的定义、使用方法及其应用场景,包括结构体与类的区别、结构体成员变量的实例化、结构体数组、结构体指针、结构体嵌套结构体等内容。

1、结构体和类的区别

结构体属于用户自定义的数据类型,其和类的定义及语法几乎一样。它们唯一的区别在于结构体默认的访问控制属性是公有类型(public),而类的默认访问控制属性是私有类型(private)

2、结构体的定义和使用

(1)、语法: struct   结构体名  {  结构体成员列表 } ;

// 创建Student的结构体
struct Student
{
	string name;
	int age;
	int score;
}s3;    // s3 为该结构体的一个变量。

int main() 
{
	// Student结构体的实例化

	// 实例化方法一:
	Student s1;
	s1.name = "Karl";
	s1.age = 18;
	s1.score = 90;
	cout << "name : " << s1.name << "age : " << s1.age << "score : " << s1.score << endl;

	// 实例化方法二:(当相应成员值缺省时,默认值为0或者空)
	Student s2 = { "Hrllt",20,99 };
	cout << "name : " << s2.name << " , age : " << s2.age << " , score : " << s2.score << endl;
	
	// 实例化方法三:在创建时就实例化s3,s3为该结构体的一个变量。
	
	cin.get();
}

(2)、结构体前有 typedef 时,其后的Stu 为结构体类型的别名。

#include<iostream>
#include<string>
using namespace std;

// Stu 为结构体Student 的别名
typedef struct Student 
{
	string name;
	int age;
}Stu;   // Stu 为该结构体类型的别名

typedef struct Student
{
	string name;
	int age;
} *ST;  // 等价于Student类型的指针: Student * 

int main()
{
	Stu s1; //等价于  Student s1;
    ST s2 = &s1; // 等价于 Student* s2=&s1 ;

	cin.get();
}

(3)、结构体数组

#include<iostream>
#include<string>
using namespace std;

// 创建Student的结构体
struct Student
{
	string name;
	int age;
	int score;
};

int main() 
{
	// 定义结构体数组的同时就对其进行初始化,只初始化前两个
	Student Array1[3] = 
	{
		{"A01",18,99},
		{"A02",20,100}
	};
	
	// 定义之后再对其进行赋值
	Array1[2].name = "A03";
	Array1[2].age = 22;
	Array1[2].score = 98;

	// 遍历结构体数组
	for (int i = 0; i < 3; i++) 
	{
		cout << Array1[i].name << "," << Array1[i].age << "," << Array1[i].score << endl;
	}

	cin.get();
}

(4)、结构体指针

#include<iostream>
#include<string>
using namespace std;

// 创建Student的结构体
struct Student
{
	string name;
	int age;
	int score;
};

int main() 
{
	// 创建结构体变量
	Student s1 = { "A01",18,100 };

	// 通过指针指向结构体变量
	Student *p = &s1;

	// 通过指针来访问结构体变量中的值
	cout << p->name << "," << p->age << "," << p->score << endl;

	cin.get();
}

(5)、结构体嵌套结构体(结构体的成员是结构体)

#include<iostream>
#include<string>
using namespace std;

// 创建Student的结构体
struct Student
{
	string name;
	int age;
	int score;
};

// 创建Teacher的结构体
struct Teacher
{
	int id;
	string name;
	int age;
	Student s2; //学生

};

int main() 
{
	// 创建Teacher结构体变量
	Teacher t1;
	t1.id = 1245;
	t1.name = "wang";
	t1.age = 50;
	t1.s2.name = "A01";
	t1.s2.age = 18;
	t1.s2.score = 100;

	cin.get();
}

(6)、结构体作为函数的参数

#include<iostream>
#include<string>
using namespace std;

// 创建Student的结构体
struct Student
{
	string name;
	int age;
	int score;
};

// 值传递的方式
void PrintStudent1(Student s) 
{
	cout << s.name << "," << s.age << "," << s.score << endl;
}

// 地址传递的方式
void PrintStudent2(Student *p) 
{
	cout << p->name << "," << p->age << "," << p->score << endl;
}
int main() 
{
	Student s6 = { "A06",20,100 };

	PrintStudent1(s6);

	PrintStudent2(&s6);  //将地址赋给指针形参

	cin.get();
}

(7)、结构体中的 const 使用

由于在调用函数的时候,如果使用的是值传递,它会把对应的数据都拷贝一份。当需要处理的数据很大时,这种方式就会占用大量的内存,增加内存开销。所以常常使用地址传递,使用指针来进行操作。但是使用指针来进行操作会很容易引起对原始数据的误修改。因此使用const关键字来对其进行限制。使其只能读,而不能修改。

#include<iostream>
#include<string>
using namespace std;

// 创建Student的结构体
struct Student
{
	string name;
	int age;
	int score;
};

// 用const来对指针变量进行修饰
void PrintStudent2(const Student *p) 
{
	// p->score = 99;此时不能修改结构体变量的值,只能读。
	cout << p->name << "," << p->age << "," << p->score << endl;
}
int main() 
{
	Student s6 = { "A06",20,100 };

	PrintStudent2(&s6);  //将地址赋给指针形参

	cin.get();
}

3、应用实例

(1)、3个老师,每个老师带2个学生。分别将3个老师和每个老师带的学生信息输出:

#include<iostream>
#include<string>
#include<ctime>
using namespace std;

// 创建Student的结构体
struct Student
{
	string sName;
	int score;
};

// 创建Teacher结构体
struct Teacher
{
	string tName;
	Student s[2];  // Student结构体为其成员变量
};

// 为Teacher的数组成员赋值,将数组作为形参传递给函数
void AllocateSpace(Teacher tArray[],int len1) 
{
	string str1 = "ABC";
	for (int i = 0;i<len1;i++) 
	{
		tArray[i].tName = "Teacher_";
		tArray[i].tName += str1[i];
		for (int j = 0; j < 2; j++) 
		{
			tArray[i].s[j].sName = "Student_";
			tArray[i].s[j].sName += str1[j];
			// 将成绩设置成为随机数
			int random = rand() % 61 + 40; //将random的值设定在40到100之间
			tArray[i].s[j].score = random;
		}
		
	}
}

void Print(const Teacher tArray[],int len) 
{
	for (int i = 0; i < len; i++) 
	{
		cout << "教师名字: " << tArray[i].tName << endl;
		for (int j = 0; j < 2; j++) {
			cout << "\t学生姓名:" << tArray[i].s[j].sName <<
				" , " << "学生成绩: " << tArray[i].s[j].score << endl;
		}
	}

}
int main() 
{
	// 设置随机数种子,以产生真正的随机数,保证公平
	srand((unsigned int)time(NULL));

	Teacher tArray[3];
	int len = sizeof(tArray) / sizeof(tArray[0]);
	AllocateSpace(tArray, len);
	Print(tArray, len);

	cin.get();
}

(2)、有5个人物的结构体数组,将5个人物的年龄按照冒泡排序法进行从大到小进行排序,并打印出来最终结果

#include<iostream>
#include<string>
#include<ctime>
using namespace std;

struct TheRole
{
	string name;
	int age;
	string gender;

};

// 冒泡排序法
void bubbleSort(TheRole Array[],int len)
{
	// 外层循环
	for (int i = 0; i < len-1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			if (Array[j].age > Array[j + 1].age) {
				TheRole temp = Array[j];
				Array[j] = Array[j + 1];
				Array[j + 1] = temp;
			}
		}
		
	}
}

// 打印结果
void PrintINfo(TheRole *role,int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << "姓名: " << role[i].name << " , " <<
			"年龄: " << role[i].age << " , " <<
			"性别: " << role[i].gender << endl;
	}
}

int main()
{
	TheRole role[5]=
	{
		{"A",23,"男"},
		{"B",22,"男"},
		{"C",20,"男"},
		{"D",21,"男"},
		{"D",19,"女"}
	};

	int len = sizeof(role) / sizeof(role[0]);
	bubbleSort(role, len);
	PrintINfo(role,len);

	cin.get();
}

参考资料:

[1]   struct和typedef struct彻底明白

### 关于C++中struct是否需要使用typedef进行重新命名 在C++编程语言中,`struct`关键字具有一定的特殊性。自C++标准引入以来,对于结构体类型的声明方式有所改进,这使得`typedef`不再是必需的工具来简化类型名称。 #### 结构体类型自动提升 从C++起始版本开始,当定义一个`struct`时,其类型名会自动被提升为全局作用域中的名字空间成员,而不需要显式的`typedef`操作[^1]。这意味着可以直接使用`struct`的名字作为类型标识符,而不必像C语言那样额外创建别名。例如: ```cpp // 不需要 typedef 的情况 struct Example { int value; }; Example example; // 正确,无需前缀 struct ``` 如果是在C语言环境下,则必须写作 `struct Example example;` 才能正确编译。但在现代C++中,这种冗余已经被移除。 #### 使用 `using` 替代传统 `typedef` 随着C++11标准的到来,推荐采用更直观且功能强大的`using`语法形式来进行类型重定义或模板参数化处理[^1]。这种方式不仅保持了清晰度还增强了灵活性。比如下面的例子展示了如何利用泛型机制构建灵活的数据容器模型: ```cpp template<typename KeyType, typename ValueType> using MapAlias = std::map<KeyType, ValueType>; MapAlias<std::string, int> myMap; // 创建了一个 string 到 int 的映射表 ``` 上述代码片段表明通过`using`可以非常方便地实现复杂的类型别名设定,相比传统的`typedef`更加简洁明了。 #### Struct的功能扩展及其优势 除了基本的数据存储之外,C++中的`struct`还可以包含成员方法以及继承特性等面向对象设计要素[^2]。因此它不仅仅局限于简单的数据聚合载体角色,而是能够承担更多职责如增强程序逻辑表达能力、促进模块划分等方面发挥重要作用。具体来说有以下几个方面的好处: - **更好的代码组织**: 将关联紧密的一组变量和操作它们的方法集中放置在一个地方有助于维护者快速理解业务场景下的交互关系。 - **加强安全性保障**: 对外部隐藏内部细节只暴露必要的接口给使用者从而减少误用风险同时保护敏感信息不被随意篡改。 - **支持复用模式开发**: 如果某些行为模式反复出现则可以通过抽象成通用解决方案降低重复劳动量并提高整体质量水平。 综上所述,在大多数情况下,尤其是在遵循现代化编码实践的时候,没有必要再单独运用`typedef`去为每一个新造出来的`struct`类另取外号;相反应该充分利用好现有的语言特性和惯用法让源码既紧凑又易于解读。 ```cpp #include <iostream> struct Person { std::string name; int age; void introduce() const { std::cout << "Hi, I'm " << name << ", and I am " << age << " years old." << std::endl; } }; int main(){ Person person{"Alice", 30}; person.introduce(); } ``` 以上实例进一步验证了这一点——即使没有任何辅助性的同义词转换措施存在,我们依然可以根据实际需求自由操控各种属性字段并且调用专属服务函数完成特定任务目标。 相关问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值