结构体:
结构体是一种特殊形态的类
- 在C语言中,结构体是一种复合数据类型,用于将多个基本类型或其他复合类型的数据组合成一个整体。
- 结构体中的成员可以是不同的类型,并且可以有不同的访问权限(在C语言中,所有成员默认都是公有的)。
- 在C语言中,结构体不支持成员函数和继承等面向对象的特性。
- 类是面向对象编程中的一个核心概念,用于描述具有相同属性和方法(或称为成员函数)的对象的集合。
- 类可以包含数据成员(即属性或字段)和成员函数(即方法)。
- 类支持封装、继承和多态等面向对象的特性。
- 在C++中,结构体与类的主要区别在于默认的访问权限。在C++中,结构体默认的数据成员和成员函数都是公有的(
public
),而类默认的数据成员和成员函数都是私有的(private
)。 - 除了访问权限的差异外,C++中的结构体和类在功能上是相似的,都可以包含数据成员、成员函数、继承等。
- 如果我们不考虑访问权限的差异,那么可以说结构体是类的一种特殊或简化形式。在C++中,你可以将结构体视为只有公有成员的类。
- 在某些情况下,当你不需要隐藏数据或提供复杂的行为时,使用结构体可能更简洁和直观。然而,对于需要封装、继承和多态等特性的复杂系统,类提供了更强大的支持。
定义的语法结构
struct 结构体名称
{
公有成员
protected:
保护型成员
private:
私有成员
}
struct MyStruct {
public:
// 公有成员,可以在类外部直接访问
int publicMember;
// 公有成员函数
void publicFunction() {
// ...
}
protected:
// 保护型成员,可以在类外部通过派生类访问,但不能直接通过实例访问
int protectedMember;
// 保护型成员函数
void protectedFunction() {
// ...
}
private:
// 私有成员,只能在类内部访问
int privateMember;
// 私有成员函数
void privateFunction() {
// ...
}
};
// 在类外部,只能访问公有成员和成员函数
int main() {
MyStruct obj;
obj.publicMember = 10; // 可以访问
obj.publicFunction(); // 可以调用
// obj.protectedMember = 20; // 错误:不能从类外部访问保护型成员
// obj.protectedFunction(); // 错误:不能从类外部调用保护型成员函数
// obj.privateMember = 30; // 错误:不能从类外部访问私有成员
// obj.privateFunction(); // 错误:不能从类外部调用私有成员函数
return 0;
}
如果结构体变量全部为公有成员,没有函数 基类等
结构体变量可以初始化(如下):
struct MyStruct {
int a;
double b;
char c;
};
int main() {
// 初始化结构体变量
MyStruct myVar = {10, 3.14, 'x'}; // 使用聚合初始化
// 现在 myVar 的成员已经被初始化为:
// myVar.a = 10
// myVar.b = 3.14
// myVar.c = 'x'
// 你也可以直接访问公有成员并修改它们
myVar.a = 20;
myVar.b = 2.71;
myVar.c = 'y';
return 0;
}
联合体:
默认访问属性:public
联合体的全部数据成员共享同一组内存单元
定义语法:
union 联合体名称{
公有成员
protected:
保护型成员
private:
私有成员
}
#include <iostream>
#include<cstring>
union MyUnion {
int i;
float f;
char str[20];
};
int main() {
MyUnion u;
// 设置int类型的值
u.i = 10;
// 注意:现在如果访问u.f或尝试解释str的内容,可能会得到不可预料的结果
// 因为它们和i共享同一块内存,而i的值已经被设置
// 设置float类型的值(会覆盖之前int的值)
u.f = 3.14f;
// 同理,如果现在访问u.i或str,内容也会被f的值覆盖
// 设置字符串(只设置前几个字符,因为float和int可能占用不同的字节数)
strcpy(u.str, "Hello");
// 访问字符串(但要注意,如果union的大小不足以存储整个字符串,则会被截断)
// 另外,如果之前设置了int或float的值,则这些值会被字符串覆盖(并且可能不会被正确地解释为字符串)
printf("%s\n", u.str);
return 0;
}
注意:
联合体不能继承 不支持包含多态
无名联合体常作为类或结构体的内嵌对象
在C++中,类可以包含各种类型的成员,包括数据成员(如整型、浮点型、字符数组等)、成员函数、嵌套类以及联合体。当联合体被嵌入到类中时,它通常用于在单个内存位置存储不同类型的值,但一次只能有一个值有效。
#include <iostream>
#include<cstring>
struct MyStruct {
int flag;
union {
int intValue;
float floatValue;
// 可以添加更多类型的成员
};
// 其他成员...
};
int main() {
MyStruct myObj;
myObj.flag = 1; // 设置标志
myObj.intValue = 42; // 访问并设置intValue
printf("%d",myObj.intValue);
return 0;
}
重要提示:虽然匿名联合体可以使代码更简洁,但它们也引入了一些潜在的问题。特别是,由于多个类型的成员共享相同的内存空间,所以必须非常小心以确保在访问某个成员之前,该成员实际上包含了你所期望的数据类型。否则,你可能会读取或写入错误的内存位置,导致未定义的行为。
#include <iostream>
#include<cstring>
class MyClass {
public:
enum ValueType {
INT_VALUE,
FLOAT_VALUE
};
ValueType type; // 用于跟踪当前有效的值类型
union { // 无名联合体
int intValue;
float floatValue;
};
// 构造函数,用于初始化联合体
MyClass(ValueType t, int i) : type(t), intValue(i) {}
MyClass(ValueType t, float f) : type(t), floatValue(f) {}
// 其他成员函数...
};
int main() {
MyClass myObj1(MyClass::INT_VALUE, 42);
std::cout << "Integer value: " << myObj1.intValue << std::endl;
MyClass myObj2(MyClass::FLOAT_VALUE, 3.14f);
std::cout << "Float value: " << myObj2.floatValue << std::endl;
// 注意:在访问联合体成员之前,最好先检查type字段以确保类型匹配
return 0;
}
需要注意的是,虽然无名联合体可以使代码更简洁,但它们也可能导致类型安全问题。因此,在使用它们时要格外小心,并确保始终正确地管理类型。在可能的情况下,使用类、继承和多态性来处理类型差异通常是更安全、更灵活的方法。
枚举类型:enum
将变量的可能值都列举出来 就构成一个枚举类型
c++包含:
不限定作用域的枚举类型
这种类型的枚举不会引入新的作用域,因此枚举的值可以在其定义的作用域中直接使用,无需枚举类型名作为前缀。但是,这也可能导致命名冲突,因为枚举的值会隐式地转换为整数类型,从而与其他的整数或枚举值混淆。
enum Color { RED, GREEN, BLUE };
int main() {
Color myColor = RED; // 不需要前缀
int num = RED; // 隐式转换为int,可能导致混淆
return 0;
}
限定作用域的枚举类型
通过关键字enum class
(或enum struct
,两者在功能上等价)来定义。这种类型的枚举会引入新的作用域,因此枚举的值必须在其自己的作用域内通过枚举类型名作为前缀来访问。此外,强类型枚举不会自动转换为其他类型(除了特定的用户定义的转换),这增加了类型安全性。
enum class Color { RED, GREEN, BLUE };
int main() {
Color myColor = Color::RED; // 需要前缀
// int num = Color::RED; // 编译错误,需要显式转换
int num = static_cast<int>(Color::RED); // 显式转换
return 0;
}
枚举类型的应用:
对枚举元素按常量处理 不能对他们赋值
枚举元素具有默认值,依次为0,1,2,3等等
可以再声明时定义枚举元素的值 未定义的按顺序默认值
整数值不能直接赋值给枚举变量 若要赋值,应该强制转化
enum Color {
RED,
GREEN,
BLUE
};
int main() {
Color myColor = RED; // 正确:将枚举值RED赋给枚举变量myColor
// myColor = 2; // 错误:不能将整数直接赋给枚举变量(除非有显式的类型转换)
// RED = GREEN; // 错误:RED是一个常量,不能重新赋值
// 但你可以通过类型转换来“模拟”赋值,但这通常不是好的做法
// int colorValue = static_cast<int>(RED);
// colorValue = 3; // 这实际上修改了整型变量colorValue,而不是枚举值RED
return 0;
}
enum Color {
RED = 1, // 显式指定RED的值为1
GREEN, // GREEN的值为RED的值加1,即2
BLUE, // BLUE的值为GREEN的值加1,即3
YELLOW = 5 // 显式指定YELLOW的值为5
// 接下来的元素如果没有显式指定值,则默认为前一个值加1
// 例如,如果这里再有一个元素,它将被默认为6
};
enum class Day : unsigned int {
SUNDAY = 0, // 显式指定SUNDAY的值为0(虽然是默认的,但这里为了明确性)
MONDAY, // MONDAY的值为SUNDAY的值加1,即1
// ... 其他元素
};
int main() {
Color myColor = Color::RED; // 正确:将枚举值RED赋给枚举变量myColor
int colorValue = RED; // 错误:RED是一个枚举值,不能直接赋给整型变量
int colorValue2 = (int)RED; // 正确:通过强制类型转换将RED转换为整型
// 或者使用static_cast,这是C++中推荐的类型转换方式
int colorValue3 = static_cast<int>(RED);
// 尝试直接将整数值赋给枚举变量会导致编译错误
// Color anotherColor = 3; // 错误:不能直接将整数赋给枚举变量
// 但可以通过强制转换来实现
Color anotherColor = static_cast<Color>(3); // 正确:但通常不推荐这样做,除非你确定值是有效的
return 0;
}
#include<iostream>
using namespace std;
enum day {
a, // 使用逗号分隔枚举成员
b,
c,
d
};
int main() {
day t = a; // 将枚举值a赋给枚举变量t
cout << t; // 直接输出枚举变量t的值,但这样可能不会按照你期望的方式显示(可能是输出数字)
// 如果要输出枚举值的名称(如"a"、"b"等),你需要自定义输出功能
// 如果你想要输出枚举值的名称(例如"a"),你需要使用其他方法,
// 比如使用switch语句或映射(map)来将枚举值映射到字符串。
// 例如,使用switch语句输出枚举值的名称:
switch (t) {
case a:
cout << "a" << endl;
break;
case b:
cout << "b" << endl;
break;
case c:
cout << "c" << endl;
break;
case d:
cout << "d" << endl;
break;
default:
cout << "Unknown day" << endl;
}
return 0;
}
标签:访问,int,成员,联合体,c++,Color,枚举,RED
From: https://blog.csdn.net/2301_82343802/article/details/139883181