在使用 Linux 下的 G++ 編譯器編譯 C++ 代碼時,經常會遇到枚舉類型使用方式與 Windows 下 Visual Studio 不同的問題。以下是一個典型的代碼示例:
#include <iostream>
enum MyEnum { F = 0, T = 1 };
bool juge(MyEnum x) {
if (x == MyEnum::F) {
return false;
} else {
return true;
}
}
int main(int argc, char** argv) {
MyEnum x = MyEnum::T;
if (juge(x)) {
std::cout << "true" << std::endl;
} else {
std::cout << "false" << std::endl;
}
return 0;
}

在 Windows 下的 VS2013 中編譯完全正常,但在 Linux 下使用 G++ 卻報錯:「既不是類也不是命名空間」。這究竟是為什麼?
這是由於 C++ 標準對於無作用域枚舉與有作用域枚舉的處理差異導致的:
F、T。MyEnum::F 這樣的語法訪問。代碼中定義的是傳統 enum,但使用了 MyEnum::F 的作用域解析語法。Visual Studio 寬容地接受了這種非標準用法,而 G++ 嚴格遵循標準,因此報錯。
將代碼改為標準的無作用域枚舉用法:
#include <iostream>
enum MyEnum { F = 0, T = 1 };
bool juge(MyEnum x) {
if (x == F) { // 直接使用枚舉值,無需 MyEnum::
return false;
} else {
return true;
}
}
int main() {
MyEnum x = T; // 同理
if (juge(x)) {
std::cout << "true" << std::endl;
} else {
std::cout << "false" << std::endl;
}
return 0;
}
如果希望保留 MyEnum::F 的寫法,應使用 enum class:
#include <iostream>
enum class MyEnum { F = 0, T = 1 }; // 注意這裡是 enum class
bool juge(MyEnum x) {
if (x == MyEnum::F) { // 現在這樣寫是合法的
return false;
}
return true;
}
int main() {
MyEnum x = MyEnum::T;
if (juge(x)) {
std::cout << "true" << std::endl;
} else {
std::cout << "false" << std::endl;
}
return 0;
}
編譯時需加上 C++11 標準標誌:g++ -std=c++11 test.cpp
set(CMAKE_CXX_STANDARD 11))。-Wall -Wextra -pedantic 等標誌,讓編譯器盡早發現不符合標準的代碼。G++ 的報錯其實是在幫助你寫出更標準、更可移植的代碼。理解無作用域枚舉與有作用域枚舉的區別,並根據項目需求選擇合適的枚舉類型,是 C++ 開發者必備的基本功。