首页 > 编程语言 >c++ 结构体 联合体 枚举

c++ 结构体 联合体 枚举

时间:2024-06-22 16:01:34浏览次数:25  
标签:访问 int 成员 联合体 c++ Color 枚举 RED

结构体:

结构体是一种特殊形态的类

  • 在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

相关文章

  • c++类的组合
    类的组合描述的是一个类内嵌其他类的对象作为成员的情况,它们之间的关系是一种包含与被包含的关系classEngine{public:voidstart(){//启动引擎的逻辑std::cout<<"Enginestarted!"<<std::endl;}//...其他引擎相关......
  • C++用扩充的结构体类型求复数的绝对值
    结构体的扩充,声明一个扩充的结构体complex,complex结构体中两个双精度数据real和imag,分别代表实数部分和虚数部分 另外还有两个属于结构体的函数:init,asbcomplex,其中init用来给real和imag赋初值,asbcomplex用来计算和返回复数的绝对值real和imag是数据成员函数init和asbcom......
  • 理解C++虚函数和虚表(vtbl)机制
    引言C++是一种强大且灵活的编程语言,它支持面向对象编程(OOP)的各种特性,其中虚函数(virtualfunction)是实现多态性(polymorphism)的关键机制。本文将深入探讨虚函数的原理、虚表(vtbl)的作用,以及这些特性在实际编程中的实现。通过理解这些概念,您将能够更好地掌握C++的多态性和面向......
  • Effective C++ 改善程序与设计的55个具体做法笔记与心得 4
    四.设计与声明18.让接口容易被正确使用,不易被误用请记住:好的接口很容易被正确使用,不容易被误用。你应该在你的所有接口中努力达成这些性质“促进正确使用”的办法包括接口的一致性,以及与内置类型的行为兼容。“阻止误用”的办法包括建立新类型、限制类型上的操作、束缚......
  • C/C++ 堆栈stack算法详解及源码
    堆栈(stack)是一种常见的数据结构,具有"先进后出"(LastInFirstOut,LIFO)的特性。堆栈算法允许在堆栈顶部进行元素的插入和删除操作。堆栈的操作包括:入栈(Push):将元素添加到堆栈的顶部。出栈(Pop):从堆栈的顶部移除元素。取栈顶元素(Top):获取堆栈顶部的元素,但不对其进行删除操作。......
  • C/C++ stack实现深度优先搜索DFS算法详解及源码
    深度优先搜索(DepthFirstSearch,DFS)是一种图遍历算法,它从一个节点开始,通过访问其相邻节点的方式,依次深入到图中的更深层次。Stack(栈)是一种先进后出(LastInFirstOut,LIFO)的数据结构,它非常适合实现DFS算法。首先,我们来解释一下Stack实现DFS算法的原理。DFS算法的核心思想是......
  • 【C++ | 重载运算符】一文弄懂C++运算符重载,怎样声明、定义运算符,重载为友元函数
    ......
  • C++PrimerPlus:第十三章类和继承:抽象基类
    :第十三章类和继承:抽象基类提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加例如::第十三章类和继承:抽象基类提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录:第十三章类和继承:抽象基类前言一、抽象基类总结前言提示:这......
  • 从0开始C++(五):友元函数&运算符重载
    友元函数介绍C++中的友元函数是一种特殊的函数,它可以访问和操作类的私有成员和保护成员。友元函数可以在类的内部或外部声明和定义,但在其声明和定义中需要使用关键字friend来标识。友元函数可以是全局函数,也可以是其他类的成员函数。下面是友元函数的一些重要特点和用法:......
  • c++ 多重包含/定义 || 链接性 || 生命周期
     作用域&&生命周期C++中的作用域(scope)指的是变量、函数或其他标识符的可见和可访问的范围。生命周期(Lifetime)指的是变量或对象存在的时间段。它开始于变量或对象的创建(定义)时刻,结束于其被销毁的时刻。作用域:通过其声明的位置来确定。全局作用域:定义在(类/函数)外部......