我尝试使用enum
(使用允许的参数)实现类(C ++)。我有一个可行的解决方案,但如果我尝试扩展功能,我就会陷入困境。
标题data_location.hpp
class DataLocation
{
private:
public:
enum Params { model, period };
std::string getParamString(Params p);
};
计划data_location.cpp
string DataLocation::getParamString(Params p){
static const char * ParamsStrings[] = {"MODEL", "PERIOD"};
return ParamsStrings[p];
}
数组ParamsStrings
通常应该在类中可用,因为我需要第二个方法(使用反函数)返回给定字符串的enum
值。
如果我尝试在标题中定义数组,我会收到错误:
in-class initialization of static data member ‘const char* DataLocation::ParamsStrings []’ of incomplete type
为什么类型不完整?编译器肯定能够计算数组中的字符串,不是吗?
如果无法使我的代码正常工作,还有其他方法吗? 1)没有XML; 2)没有字符串的双重定义; 3)不在课外; 4)代码编程映射中没有。
答案 0 :(得分:0)
在课程(标题)中使用关键字static
并在没有static
关键字的情况下在(.cpp)之外初始化它:
class DataLocation {
public:
enum Params { model, period };
string getParamString(Params p);
static const char* ParamsStrings[];
// ^^^^^^
};
const char* DataLocation::ParamsStrings[] = {"MODEL", "BLLBLA"};
//^^^^^^^^^^^^^^^^^^^^^^^^
答案 1 :(得分:0)
您发布的代码非常好。
以下是证据:
#include <iostream>
#include <string>
struct DataLocation
{
enum Params { model, period };
std::string getParamString(Params p){
static const char * ParamsStrings[] = {"MODEL", "PERIOD"};
return ParamsStrings[p];
}
};
int main()
{
auto a = DataLocation();
std::cout << a.getParamString(DataLocation::model) << std::endl;
return 0;
}
您获得的错误消息与内联函数中静态数据成员的定义无关 - 这是允许的。
还有一些你没有向我们展示的东西。
答案 2 :(得分:0)
我的问题(第二部分)中的主要问题是,如果我在.hpp和.cpp中拆分类,那么数组的定义(我混合了* char和string)也必须拆分:
// data_location.hpp
class DataLocation {
static const char * ParamsStrings[];
}
// data_location.cpp
const char * ParamsStrings[] = {"MODEL", "PERIOD"};
最后,我介绍了一致性检查,以确保enum
中的值数增长为字符串数。因为C ++中的数组在某种程度上是有限的,所以我必须选择std::vector
(以获得大小)。
data_location.hpp
的代码
#ifndef DATA_LOCATION_HPP_
#define DATA_LOCATION_HPP_
#include <string>
#include "utils/dictionary.hpp"
extern const char* ENV_DATA_ROOT;
struct EDataLocationInconsistency : std::runtime_error
{
using std::runtime_error::runtime_error;
};
struct EDataLocationNotValidParam : std::runtime_error
{
using std::runtime_error::runtime_error;
};
class DataLocation
{
private:
std::string mRootLocation;
static const std::vector<std::string> msParamsStrings;
static bool msConsistenceCheckDone;
public:
DataLocation();
std::string getRootLocation();
std::string getLocation(Dictionary params);
enum Params { model, period, LAST_PARAM};
std::string Param2String(Params p);
Params String2Param(std::string p);
};
#endif
data_location.cpp
的代码
#include "data_location.hpp"
#include <string>
#include <cstdlib>
using namespace std;
const char* ENV_DATA_ROOT = "DATA_ROOT";
bool DataLocation::msConsistenceCheckDone = false;
DataLocation::DataLocation() {
mRootLocation = std::getenv(ENV_DATA_ROOT);
if (not msConsistenceCheckDone) {
msConsistenceCheckDone = true;
if (LAST_PARAM+1 != msParamsStrings.size()) {
throw(EDataLocationInconsistency("DataLocation: Check Params and msParamsStrings"));
}
}
}
string DataLocation::getRootLocation() {
return mRootLocation;
}
string DataLocation::getLocation(Dictionary params) {
// to do
return "";
}
const vector<string> DataLocation::msParamsStrings = { "MODEL", "PERIOD", ""};
string DataLocation::Param2String(Params p) {
if (p>=msParamsStrings.size()) {
throw(EDataLocationNotValidParam("Parameter not found"));
}
return msParamsStrings[p];
}
DataLocation::Params DataLocation::String2Param(string p) {
for (int i = 0; i < msParamsStrings.size(); i++) {
if (p == msParamsStrings[i])
return (Params)i;
}
throw(EDataLocationNotValidParam("Parameter not found"));
}
还有单元测试:
#include <boost/test/unit_test.hpp>
#include "data_location.hpp"
#include <string>
using namespace std;
BOOST_AUTO_TEST_SUITE( data_location )
BOOST_AUTO_TEST_CASE(data_location_1) {
DataLocation dl;
auto s = dl.getRootLocation();
BOOST_CHECK_EQUAL(s, "/home/tc/data/forex" );
BOOST_CHECK_EQUAL(dl.Param2String(DataLocation::period),"PERIOD");
BOOST_CHECK_EQUAL(dl.String2Param("PERIOD"),DataLocation::period);
BOOST_CHECK_THROW(dl.String2Param("SOMETHING"), EDataLocationNotValidParam);
BOOST_CHECK_THROW(dl.Param2String((DataLocation::Params)100), EDataLocationNotValidParam);
}
BOOST_AUTO_TEST_SUITE_END()
答案 3 :(得分:-1)
C ++非常挑剔它可以让你在类定义中初始化;围绕static
成员有一些特别不直观的规则。这一切都与ODR有关,为什么所有规则都是这样的并不是特别重要。
要切换到追逐,使您的数组成为static constexpr const
成员应该关闭编译器。使用C ++ 11标准时,限制有所放松,其中一项新规定是static constexpr
成员可以内联初始化。这非常适合您的应用程序,因为数组中的字符串是编译时常量。
答案 4 :(得分:-1)
最近支持C ++ 0x或更高版本的g ++编译器编译代码。 Pure C编译也编译。因为像{"MODEL", "PERIOD"};
这样的初始化中的字符串实现为指向char数组的const char *
指针。