在带有字符串的类中枚举

时间:2016-04-03 07:02:23

标签: c++ enums

我尝试使用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)代码编程映射中没有。

5 个答案:

答案 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 *指针。