C/CPP: Enum Class vs. Enum Type

本文介绍了C++中的枚举类型及其限制,强调了枚举类(enum class)的优势。枚举类提供强类型和作用域保护,避免了枚举值之间的隐式转换和名称冲突问题,增强了代码的类型安全。同时,枚举类还可以指定底层数据类型,控制枚举的大小。示例代码展示了枚举类的使用和错误处理情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

from: Enum Classes in C++ and Their Advantage over Enum DataType - GeeksforGeeksicon-default.png?t=LA92https://www.geeksforgeeks.org/enum-classes-in-c-and-their-advantage-over-enum-datatype/

Enums or Enumerated type (enumeration) is a user-defined data type that can be assigned some limited values. These values are defined by the programmer at the time of declaring the enumerated type.

Need for Enum Class over Enum Type: 
Below are some of the reasons as to what are the limitations of Enum Type and why we need Enum Class to cover them.

Two enumerations cannot share the same names (of values): 

#include <bits/stdc++.h>

using namespace std;



int main()

{

    // Defining enum1 Gender

    enum Gender { Male,

                  Female };



    // Defining enum2 Gender2 with same values

    // This will throw error

    enum Gender2 { Male,

                   Female };



    // Creating Gender type variable

    Gender gender = Male;

    Gender2 gender2 = Female;



    cout << gender << endl

         << gender2;



    return 0;

}

Compilation Error: 

prog.cpp:13:20: error: redeclaration of 'Male'
     enum Gender2 { Male,
                    ^
prog.cpp:8:19: note: previous declaration 'main()::Gender Male'
     enum Gender { Male,
                   ^
prog.cpp:14:20: error: redeclaration of 'Female'
                    Female };
                    ^
prog.cpp:9:19: note: previous declaration 'main()::Gender Female'
                   Female };
                   ^
prog.cpp:18:23: error: cannot convert 'main()::Gender' 
to 'main()::Gender2' in initialization
     Gender2 gender2 = Female;
                       ^

No variable can have a name which is already in some enumeration:

#include <bits/stdc++.h>

using namespace std;



int main()

{

    // Defining enum1 Gender

    enum Gender { Male,

                  Female };


    // Creating Gender type variable

    Gender gender = Male;


    // creating a variable Male

    // this will throw error

    int Male = 10;


    cout << gender << endl;


    return 0;

}

Compilation Error: 

prog.cpp: In function 'int main()':
prog.cpp:16:9: error: 'int Male' redeclared as different kind of symbol
     int Male = 10;
         ^
prog.cpp:8:19: note: previous declaration 'main()::Gender Male'
     enum Gender { Male,
                   ^

Enums are not type-safe:
 

#include <bits/stdc++.h>

using namespace std;



int main()

{

    // Defining enum1 Gender

    enum Gender { Male,

                  Female };



    // Defining enum2 Color

    enum Color { Red,

                 Green };



    // Creating Gender type variable

    Gender gender = Male;

    Color color = Red;



    // Upon comparing gender and color

    // it will return true as both have value 0

    // which should not be the case actually

    if (gender == color)

        cout << "Equal";



    return 0;

}

Warning: 

prog.cpp: In function 'int main()':
prog.cpp:23:19: warning: comparison between 'enum main()::Gender'
and 'enum main()::Color' [-Wenum-compare]
     if (gender == color)                ^

Enum Class

C++11 has introduced enum classes (also called scoped enumerations), that makes enumerations both strongly typed and strongly scoped. Class enum doesn’t allow implicit conversion to int, and also doesn’t compare enumerators from different enumerations.
To define enum class we use class keyword after enum keyword. 
Syntax: 

// Declaration
enum class EnumName{ Value1, Value2, ... ValueN};

// Initialisation
EnumName ObjectName = EnumName::Value;

Example: 

// Declaration
enum class Color{ Red, Green, Blue};

// Initialisation
Color col = Color::Red;

Below is an implementation to show Enum Class
 

// C++ program to demonstrate working

// of Enum Classes



#include <iostream>

using namespace std;



int main()

{



    enum class Color { Red,

                       Green,

                       Blue };

    enum class Color2 { Red,

                        Black,

                        White };

    enum class People { Good,

                        Bad };



    // An enum value can now be used

    // to create variables

    int Green = 10;



    // Instantiating the Enum Class

    Color x = Color::Green;



    // Comparison now is completely type-safe

    if (x == Color::Red)

        cout << "It's Red\n";

    else

        cout << "It's not Red\n";



    People p = People::Good;



    if (p == People::Bad)

        cout << "Bad people\n";

    else

        cout << "Good people\n";



    // gives an error

    // if(x == p)

    // cout<<"red is equal to good";



    // won't work as there is no

    // implicit conversion to int

    // cout<< x;



    cout << int(x);



    return 0;

}

Output

It's not Red
Good people
1

Enumerated types declared within the enum class also have more control over their underlying type; it may be any integral data type, such as char, short or unsigned int, which essentially serves to determines the size of the type.

This is specified by a colon and underlying type following the enumerated type:

eg: enum class eyecolor : char {char,green,blue};
Here eyecolor is a distinct type with the same size as a char (1 byte).

#include <iostream>

using namespace std;

enum rainbow{

    violet,

    indigo,

    blue,

    green,yellow,orange,red

}colors;

enum class eyecolor:char{

    blue,green,brown

}eye;

int main() {

    cout<<"size of enum rainbow variable: "<<sizeof(colors)<<endl;

    cout<<"size of enum class eyecolor variable:"<<sizeof(eye)<<endl;

    return 0;

}

Output

size of enum rainbow variable: 4
size of enum class eyecolor variable:1

Reference: Enumeration declaration - cppreference.com
 

<think>好的,我现在需要帮助用户将提供的Kotlin代码集成到他们的现有Android工程中。首先,我得理解用户的问题。他们提供了一段涉及JNI的蓝牙操作代码,询问如何将这些代码添加到已有项目中。用户可能是一个Android开发者,对JNI和蓝牙开发有一定了解,但在集成过程中可能遇到问题。 首先,我需要分析用户提供的代码结构。BluetoothReaderJNI是一个object类,包含初始化动态库的代码和几个external方法,这些是JNI的本地方法。还有错误码的枚举和一个使用示例类BluetoothService。用户可能已经配置了部分内容,但需要指导完整的集成步骤。 接下来,我应该考虑如何分步骤引导用户添加代码。可能包括以下几个部分:创建Kotlin文件、配置JNI目录、编写本地代码、配置CMakeLists.txt、处理权限等。需要确保每一步都清晰,特别是JNI相关的配置,因为这是容易出错的地方。 然后,我要考虑用户可能遇到的问题。比如,是否正确加载了.so库,CMakeLists.txt是否正确配置,权限是否添加,以及本地方法的命名是否符合JNI规范等。需要提醒用户检查这些点,并提供示例代码或配置片段。 另外,用户可能不熟悉JNI的开发流程,可能需要详细说明如何创建本地方法,生成头文件,以及编译动态库的过程。这部分需要逐步解释,避免遗漏关键步骤。 最后,应该给出一个完整的集成步骤列表,并附上注意事项和验证方法,确保用户能够顺利运行代码。同时,要提醒用户测试蓝牙功能时所需的设备和权限,确保实际运行环境正确。</think>以下是分步骤将这段蓝牙 JNI 代码集成到 Android 工程的完整指南: --- ### 一、文件结构准备 ```bash app/ ├── src/ │ ├── main/ │ │ ├── java/ # 或 kotlin/ │ │ │ └── com/example/app/ │ │ │ ├── BluetoothReaderJNI.kt # 新增文件 │ │ │ └── BluetoothService.kt # 新增文件 │ │ ├── jni/ │ │ │ ├── bluetooth_native.cpp # C++实现文件 │ │ │ └── CMakeLists.txt # JNI构建配置 │ │ └── cpp/ # 或使用该目录(需对应配置) ``` --- ### 二、关键集成步骤 #### 1. 添加 Kotlin 文件 - 将 `BluetoothReaderJNI` 和 `BluetoothService` 类文件放置到对应包路径 - **注意**:包名必须与 C++ 代码中的 JNI 函数包名匹配 #### 2. 配置 JNI 目录(build.gradle) ```kotlin android { defaultConfig { externalNativeBuild { cmake { cppFlags "-std=c++17" // 如果使用多个ABI可以指定 // abiFilters "armeabi-v7a", "arm64-v8a" } } } externalNativeBuild { cmake { path "src/main/jni/CMakeLists.txt" // 指向CMake配置文件 } } sourceSets { main { jniLibs.srcDirs = ['src/main/jni'] // JNI代码目录 } } } ``` #### 3. 编写 C++ 实现(bluetooth_native.cpp) ```cpp #include <jni.h> #include <string> // 必须与Java包名匹配(示例包名:com.example.app) extern "C" JNIEXPORT jint JNICALL Java_com_example_app_BluetoothReaderJNI_initBluetooth(JNIEnv* env, jobject /* this */) { // 实际蓝牙初始化代码 return 0; // 返回SUCCESS值 } // 其他函数按相同模式实现... ``` #### 4. 配置 CMakeLists.txt ```cmake cmake_minimum_required(VERSION 3.10.2) project("bluetooth_native") add_library( bluetooth_native # 必须与System.loadLibrary名称一致 SHARED bluetooth_native.cpp ) find_library( log-lib log ) target_link_libraries( bluetooth_native ${log-lib} ) ``` --- ### 三、必要权限配置(AndroidManifest.xml) ```xml <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <!-- API 23+需要 --> ``` --- ### 四、JNI开发注意事项 1. **函数签名匹配** C++ 函数名必须遵循格式: `Java_包名_类名_方法名` 例如:`Java_com_example_app_BluetoothReaderJNI_connectDevice` 2. **线程安全** JNI 调用需注意线程切换,建议通过 `AttachCurrentThread` 处理 3. **内存管理** - 本地代码创建的 `jobject` 需用 `env->NewGlobalRef()` 转为全局引用 - 及时释放本地引用 `env->DeleteLocalRef()` 4. **异常处理** 在 JNI 层通过 `env->ThrowNew()` 抛出 Java 异常 --- ### 五、验证流程 1. 编译生成 .so 文件 Build > Make Project 后检查 `build/intermediates/cmake` 目录 2. 运行时检查库加载 如果出现 `UnsatisfiedLinkError`,说明: - 函数签名错误 - .so 文件未正确打包进 APK 3. 使用 Android Profiler 监控 JNI 内存泄漏和线程状态 --- ### 六、完整集成示例 [GitHub 示例工程](https://github.com/android/ndk-samples/tree/master/hello-jni)(参考 JNI 集成方式)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值