2016-04-03 127 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()