创建结构作为枚举类成员
Creating a struct as enum class member
我正在努力为库创建一个多级枚举。
- 我想要这样的东西(不一定完全是(:
Book::Category::PROGRAMMING::C_PLUS_PLUS
其中Book
是struct
,Category
(目前(是enum class
。
基本上,我想嵌套枚举。
我知道我可以做:
Book::Category::PROGRAMMING_C_PLUS_PLUS
但是这不仅会在Category
中创建一长串值,而且会使维护它成为一场噩梦(我尝试用 30 这样做,这已经是一个令人头疼的问题(。
我想分而治之,克服这个问题。
编辑1:我不希望它成为std::string
的原因是它的价值可以是任何东西。我想限制Category
的领域.
不,PROGRAMMING
不是我图书馆的主要部分。让我尝试使用类和继承。
基本上,我想要enum
的原因是有一组固定的有效常量。
引用:
- 枚举类可以嵌套吗? ->我需要创建
Book
的对象,因此它不能是命名空间。我无法理解使用模板的答案。 - 为什么枚举类比普通枚举更受欢迎? -> 没有回答我的问题。
您不能嵌套enum
s,但是,您可以执行以下操作:
struct Book {
struct Category {
enum class PROGRAMMING {
// ...
};
enum class COOKING {
// ...
};
};
};
类似于在链接问题中使用命名空间,但由于它位于类内部并且您无法这样做,因此您可以只使用另一个结构。
你可以这样做,但这将是一个糟糕的设计。
一种常见的代码气味是使用enum
来表示显然应该是一个类 - 这里的情况是您希望C_PLUS_PLUS
类型是PROGRAMMING
类别的派生。
但是,enum
最好用于描述可能的状态,并且无法通过设计进行继承,如您在其中一个参考中指出的那样。在我看来,你最好的做法是在Category
中制作两个单独的成员变量,它们可以保存PROGRAMMING
和C_PLUS_PLUS
等值,并取消它们作为enum
s 的状态。
思考:什么最能概括一个开放式领域,如书籍类型/子类型?您是否打算用enum
对每种可能性进行编程?或者只使用两个string
(例如genre
和subgenre
(更适合这样的开放式字段?
或者,也许,如果你专门使用PROGRAMMING
书籍作为你设计的主要部分,PROGRAMMING
变成一个类,C_PLUS_PLUS
成为该类中enum
的一部分。但是不要让它们都enums
- 这只是在路上提出问题,并不能解决您已经描述的维护问题。
编辑:从我发表的评论中添加 -
通过强迫它们固定和恒定,无论如何你都会强迫自己陷入"头痛"的境地。你强迫自己维护一个恒定的有效枚举列表,这些枚举可能会在某个时候发生变化,此时你必须更新枚举列表并重新编译代码。这里的一个可塑性解决方案是允许它们是字符串,并在启动或其他东西时读取.txt文件,并将其作为可接受的值列表,如果需要验证,您可以检查这些值。
应应回答者的要求,我发布我的实现以供将来参考。
这是Book
:
struct Book
{
// A Map of categories and its list of sub-categories
static std::map< std::string, std::vector< std::string > > Categories;
// default parameter for unit testing,
// thanks to https://stackoverflow.com/questions/40297782/c-unit-testing-check-output-is-correct/59374648#59374648
static void initBookCategories(std::string file_name = "categories.txt")
{
// Open the file in read mode
std::ifstream allowed_categories(file_name);
// Check if file open is unsuccessful
if(!allowed_categories)
{
// Signal error and exit
std::cerr << "nnFile Not Found!nError Initialising DB! Exiting...";
return;
}
// Read the category_name
std::string category_name;
// Until there are categories left
while(std::getline(allowed_categories, category_name))
{
// Read the whole sub-category list
std::string subcategory_names;
// Untill end of line
std::getline(allowed_categories, subcategory_names);
// Convert to std::stringstream for parsing
std::istringstream parse_subcategories(subcategory_names);
// Skip the empty line
allowed_categories.ignore();
// Now read the sub-categories
// Need a std::vector to store the list of subcategory names
std::vector< std::string > subcategory_list;
// Reusing subcategory_names for each subcategory_name
while(parse_subcategories >> subcategory_names)
{
// Add to the list of sub-categories
subcategory_list.push_back(subcategory_names);
}
// Add this newly read category with its list of subcategories our map
Categories.insert(std::pair< std::string, std::vector< std::string > >(category_name, subcategory_list));
}
}
static void getCategoryList()
{
// For each category
for(std::pair< const std::string, std::vector< std::string > >& category : Categories)
{
// List the sub-categories
int index = 0;
// Print the category name
std::cout << " " << category.first << ":n";
// Loop over the sub-categories
for(std::string& subcategory_name : category.second)
{
// Printing each sub-category in a line
std::cout << " " << ++index << ") " << subcategory_name << "n";
}
}
}
};
std::map< std::string, std::vector< std::string > > Book::Categories;
我们的主要函数使用它:
int main()
{
Book::initBookCategories();
Book::getCategoryList();
return 0;
}
最后但并非最不重要的一点是,categories.txt
格式:
PROGRAMMING
C_PLUS_PLUS C PYTHON JAVA SQL
MATHEMATICS
CALCULUS ALGEBRA DISCRETE
BIOLOGY
ZOOLOGY BOTANY MICROBIOLOGY BIOTECHNOLOGY
CHEMISTRY
ORGANIC INORGANIC PHYSICAL
SOCIAL_STUDIES
POLITICAL_SCIENCE GEOGRAPHY HISTORY CIVIL_SCIENCE
BUSINESS_ADMINISTRATION
ACCOUNTS MANAGEMENT STATISTICS ECONOMICS
SCIENCE_FICTION
SPACE ALIENS FUTURE WAR ADVENTURE
LITERATURE
ENGLISH HINDI COMEDY NOVEL
PHYSICS
MECHANICS FLUIDS NUCLEAR THERMODYNAMICS
ARTS_AND_HUMANITIES
PHILOSOPHY SOCIOLOGY PSYCHOLOGY ANTHROPOLOGY
谢谢!
- 枚举成员与静态 int 成员?
- 为什么不能直接引用作用域枚举类成员,而不能为无作用域枚举生成类成员?
- 创建结构作为枚举类成员
- 从类访问枚举成员
- 两个枚举可以不具有相似名称的成员吗
- 为什么允许将整型、枚举和指向成员的指针类型reinterpret_cast到自身?
- 是否可以基于私有/受保护成员分配类枚举?
- 枚举成员不是类型错误
- std::映射键作为模板化结构与枚举成员
- 设置类的枚举成员无效地使用"枚举"
- 将C 枚举类成员拉入全局名称空间
- 枚举不是非静态数据成员或类的基类
- C++ 成员函数的多个定义,基于枚举模板参数
- 当枚举器列表项的标识符已是结构的成员时,如何使用枚举器列表项
- 我们可以专业化类模板的枚举(类型)成员吗?
- 将成员枚举变量传递给类构造函数时出现无效的重定义错误
- 如何访问其他类的成员枚举 (c++)
- 位掩码作为具有默认参数的成员枚举
- 前向声明类模板的成员枚举
- 静态常量成员值与成员枚举:哪种方法更好以及为什么?