Java C++ 中的样式枚举 类
Java Style Enum Classes in C++
我正在尝试为类似于 Java 枚举的数据类型实现枚举 class。
DataType.h:
namespace Galactose {
class DataType {
public:
DataType(const std::string& a_name, const size_t a_byteSize);
DataType(const std::string& a_name, const DataType& a_componentType, const uint32_t a_componentCount);
private:
inline static std::vector<DataType> s_types;
int32_t m_ordinal;
std::string m_name;
size_t m_byteSize;
const DataType& m_componentType;
uint32_t m_componentCount;
};
namespace DataTypes {
inline static const DataType FLOAT(GT_STRINGIFY(FLOAT), sizeof(float));
inline static const DataType VECTOR2(GT_STRINGIFY(VECTOR2), FLOAT, 2);
inline static const DataType VECTOR3(GT_STRINGIFY(VECTOR3), FLOAT, 3);
inline static const DataType VECTOR4(GT_STRINGIFY(VECTOR4), FLOAT, 4);
};
}
DataType.cpp:
#include "DataType.h"
namespace Galactose {
DataType::DataType(const std::string& a_name, const size_t a_byteSize)
: m_ordinal(int32_t(s_types.size())),
m_name(a_name),
m_byteSize(a_byteSize),
m_componentType(*this),
m_componentCount(1)
{
s_types.emplace_back(*this);
}
DataType::DataType(const std::string& a_name, const DataType& a_componentType, const uint32_t a_componentCount)
: m_ordinal(int32_t(s_types.size())),
m_name(a_name),
m_byteSize(a_componentType.m_byteSize * a_componentCount),
m_componentType(a_componentType),
m_componentCount(a_componentCount)
{
s_types.emplace_back(*this);
}
}
GT_STRINGIFY
在这样的预编译头文件中定义:
#define GT_STRINGIFY(x) #x
问题是 DataTypes
中的变量被多次实例化。可能每个 #include "DataType.h"
一次。我希望它们只被实例化一次。
我试图将 DataTypes
namespace
更改为 class
,但在每个 GT_STRINGIFY
处给出 Error C2059 syntax error: 'string'
。
我知道我可以检查 name 是否已经存在,或者使用 set 而不是 vector。但是我真的不想走这条路。
感谢您的宝贵时间。欢迎任何建议。
使用其他语言 tools/techniques 通常不是前进的方向,因此我向您推荐 enum class
(它是特定于 C++ 的,可能是您将获得的最接近的内置内容)。
Why is enum class preferred over plain enum?
另外需要注意的是你需要头部防护:
Header guards in C++ and C 基本上是这样的:
#ifndef HEADER_NAME_HPP
#define HEADER_NAME_HPP
//code
#endif
static
在命名空间范围内的一个变量上意味着这个变量在使用这个 header 的每个翻译单元(.cpp 文件)中存在一次。确保所有翻译单元共享相同 object 的方法是将这些变量声明为 extern
并在 DataType.cpp
.
中定义它们
DataType.h:
...
namespace DataTypes {
extern const DataType FLOAT;
extern const DataType VECTOR2;
extern const DataType VECTOR3;
extern const DataType VECTOR4;
};
...
DataType.cpp:
...
namespace DataTypes {
const DataType FLOAT("FLOAT", sizeof(float));
const DataType VECTOR2("VECTOR2", FLOAT, 2);
const DataType VECTOR3("VECTOR3", FLOAT, 3);
const DataType VECTOR4("VECTOR4", FLOAT, 4);
};
...
为了更接近 java 枚举,您可能希望在 DataType
中将符号声明为静态变量,而不是允许您通过例如引用它们Galactose::DataType::FLOAT
.
...
class DataType {
public:
DataType(const std::string& a_name, const size_t a_byteSize);
DataType(const std::string& a_name, const DataType& a_componentType, const uint32_t a_componentCount);
static const DataType FLOAT;
static const DataType VECTOR2;
static const DataType VECTOR3;
static const DataType VECTOR4;
private:
...
};
...
DataType.cpp:
...
const DataType DataType::FLOAT("FLOAT", sizeof(float));
const DataType DataType::VECTOR2("VECTOR2", FLOAT, 2);
const DataType DataType::VECTOR3("VECTOR3", FLOAT, 3);
const DataType DataType::VECTOR4("VECTOR4", FLOAT, 4);
...
您当然可以使用包含静态成员的单独 class,但这与 java 不同,其中枚举常量可通过枚举类型访问。
我在这个回答中假设您的 header 文件没有完整发布。否则你应该添加 header 守卫以避免在通过多个其他 header 间接包含此文件时出现问题;此外,您应该为所有使用的类型添加包含。 header 中将缺少以下内容:
#include <string>
#include <vector>
我正在尝试为类似于 Java 枚举的数据类型实现枚举 class。
DataType.h:
namespace Galactose {
class DataType {
public:
DataType(const std::string& a_name, const size_t a_byteSize);
DataType(const std::string& a_name, const DataType& a_componentType, const uint32_t a_componentCount);
private:
inline static std::vector<DataType> s_types;
int32_t m_ordinal;
std::string m_name;
size_t m_byteSize;
const DataType& m_componentType;
uint32_t m_componentCount;
};
namespace DataTypes {
inline static const DataType FLOAT(GT_STRINGIFY(FLOAT), sizeof(float));
inline static const DataType VECTOR2(GT_STRINGIFY(VECTOR2), FLOAT, 2);
inline static const DataType VECTOR3(GT_STRINGIFY(VECTOR3), FLOAT, 3);
inline static const DataType VECTOR4(GT_STRINGIFY(VECTOR4), FLOAT, 4);
};
}
DataType.cpp:
#include "DataType.h"
namespace Galactose {
DataType::DataType(const std::string& a_name, const size_t a_byteSize)
: m_ordinal(int32_t(s_types.size())),
m_name(a_name),
m_byteSize(a_byteSize),
m_componentType(*this),
m_componentCount(1)
{
s_types.emplace_back(*this);
}
DataType::DataType(const std::string& a_name, const DataType& a_componentType, const uint32_t a_componentCount)
: m_ordinal(int32_t(s_types.size())),
m_name(a_name),
m_byteSize(a_componentType.m_byteSize * a_componentCount),
m_componentType(a_componentType),
m_componentCount(a_componentCount)
{
s_types.emplace_back(*this);
}
}
GT_STRINGIFY
在这样的预编译头文件中定义:
#define GT_STRINGIFY(x) #x
问题是 DataTypes
中的变量被多次实例化。可能每个 #include "DataType.h"
一次。我希望它们只被实例化一次。
我试图将 DataTypes
namespace
更改为 class
,但在每个 GT_STRINGIFY
处给出 Error C2059 syntax error: 'string'
。
我知道我可以检查 name 是否已经存在,或者使用 set 而不是 vector。但是我真的不想走这条路。
感谢您的宝贵时间。欢迎任何建议。
使用其他语言 tools/techniques 通常不是前进的方向,因此我向您推荐 enum class
(它是特定于 C++ 的,可能是您将获得的最接近的内置内容)。
Why is enum class preferred over plain enum?
另外需要注意的是你需要头部防护: Header guards in C++ and C 基本上是这样的:
#ifndef HEADER_NAME_HPP
#define HEADER_NAME_HPP
//code
#endif
static
在命名空间范围内的一个变量上意味着这个变量在使用这个 header 的每个翻译单元(.cpp 文件)中存在一次。确保所有翻译单元共享相同 object 的方法是将这些变量声明为 extern
并在 DataType.cpp
.
DataType.h:
...
namespace DataTypes {
extern const DataType FLOAT;
extern const DataType VECTOR2;
extern const DataType VECTOR3;
extern const DataType VECTOR4;
};
...
DataType.cpp:
...
namespace DataTypes {
const DataType FLOAT("FLOAT", sizeof(float));
const DataType VECTOR2("VECTOR2", FLOAT, 2);
const DataType VECTOR3("VECTOR3", FLOAT, 3);
const DataType VECTOR4("VECTOR4", FLOAT, 4);
};
...
为了更接近 java 枚举,您可能希望在 DataType
中将符号声明为静态变量,而不是允许您通过例如引用它们Galactose::DataType::FLOAT
.
...
class DataType {
public:
DataType(const std::string& a_name, const size_t a_byteSize);
DataType(const std::string& a_name, const DataType& a_componentType, const uint32_t a_componentCount);
static const DataType FLOAT;
static const DataType VECTOR2;
static const DataType VECTOR3;
static const DataType VECTOR4;
private:
...
};
...
DataType.cpp:
...
const DataType DataType::FLOAT("FLOAT", sizeof(float));
const DataType DataType::VECTOR2("VECTOR2", FLOAT, 2);
const DataType DataType::VECTOR3("VECTOR3", FLOAT, 3);
const DataType DataType::VECTOR4("VECTOR4", FLOAT, 4);
...
您当然可以使用包含静态成员的单独 class,但这与 java 不同,其中枚举常量可通过枚举类型访问。
我在这个回答中假设您的 header 文件没有完整发布。否则你应该添加 header 守卫以避免在通过多个其他 header 间接包含此文件时出现问题;此外,您应该为所有使用的类型添加包含。 header 中将缺少以下内容:
#include <string>
#include <vector>