2016-04-03 26 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]; 
} 

アレイIが(逆関数を用いて)第二の方法を必要とするのでParamsStringsenum値を返す、クラスで一般的に利用可能であるべきであるが与えられます文字列。

私は、ヘッダーに配列を定義しようとすると、私はエラーを取得する:

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標準では、制限が少し緩和され、新しい規定の1つは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

私の質問(第2部)の主な問題は、クラスを.hppと.hppで分割した場合です。CPPは、配列の定義は、(私が混入*文字と文字列)も分割する必要があります:終わり

// data_location.hpp 
class DataLocation { 
    static const char * ParamsStrings[]; 
} 
// data_location.cpp 
const char * ParamsStrings[] = {"MODEL", "PERIOD"}; 

は、私が確認するために、整合性チェックを導入している数としてenum成長中の値の数文字列。 C++の配列は何とか制限されていたので、サイズを取得するためにはstd::vectorに行っていました。

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

ため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 

コードのためのコードと、単位テスト:

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