2016-04-03 124 views
0

我试图用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

你必须声明在头的阵列,且在其定义CPP。 – Zereges

+0

你的问题归结为“我如何定义静态类成员?”有足够的现有代码。另外,如果您想要解释错误消息,请提供完整(但最少)的示例代码。 –

+0

感谢您的意见。你是对的,看到我的评论@ blazs的答案 – LiPo

回答

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"}; 
//^^^^^^^^^^^^^^^^^^^^^^^^ 
+0

这是我的问题中的错误的原因。 – LiPo

-1

C++是非常挑剔的,它会让你初始化类定义的内部;围绕static成员有一些特别不直观的规则。这一切都与ODR有关,为什么所有的规则都是它们的方式不是特别重要。

要切换到追逐模式,使您的数组成员为static constexpr const成员应该关闭编译器。在C++ 11标准中,这些限制被放宽了一点,其中一个新规定是static constexpr成员可以被内联初始化。这对于您的应用程序来说是完美的,因为数组中的字符串是编译时常量。

-1

最近支持C++ 0x或更高版本的g ++编译器编译代码。纯C编译也是如此。因为像{"MODEL", "PERIOD"};这样的初始化字符串实现为const char *指向char数组的指针。

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; 
} 

你所得到的错误消息不是做一个静态数据成员的定义在一个内联函数 - 这是允许的。

还有别的东西你没有告诉我们。

+0

我同意,但由于我**错误**拆分.hpp和.cpp中的代码(如我的问题)我得到了提到的错误 – LiPo

0

我的问题(第二部分)的主要问题是,如果我在.hpp和。CPP阵列的定义(I混合* char和串)也被分割:

// 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()