如何在程序中的两个类中声明/定义一次并使用地图列表?

时间:2015-04-27 16:18:19

标签: c++ c++11

我正在用C ++ 11开发一个程序,我需要在两个类中使用C ++ STL映射。 在使用的2个位置中,地图具有相同的键和值列表。

这些类用于程序的不同部分:

// in other part of the program
void check_something()
{
    // the size of the list can be 100, 200 or ...
    map<string, string> amap{
        {"something", "nothing"},
        {"key", "value"},
    };

    SameClass sc{amap};
    // use sc
}

// in other part of the program
void check_other_thing()
{
    // the size of the list can be 100, 200 or ...
    map<string, string> amap_2{
        {"something", "nothing"},
        {"key", "value"},
    };

    SameClass sx{amap_2};
    // use sx
}

现在这可以(用于测试),但我想知道(用于维护和优化)如何声明和定义一次,然后在程序中的任何地方使用地图?

我是否需要创建一个将地图放在shared_ptr&lt;&gt;中的类或结构或函数?并返回地图?

我不想使用全局变量!

4 个答案:

答案 0 :(得分:1)

如果您想在程序中使用变量WHEREVER,我们就会谈论您不想使用的全局变量(这很好!)。

另一种方法是使用静态变量创建类,它类似于全局变量,但不会创建名称冲突

float var = Variables::numba

您可以像void setMap(map<string, string> &map) //note ampersand, it has to be a reference { mMap = map //where mMap means member variable in your class }

一样使用它

您还可以让函数返回对您的变量的引用,然后将其存储为指针。这实际上是更好的主意,因为你不会使用任何类型的全局变量。

因此,在某处创建地图并将其传递给对象

{{1}}

如果您希望所有SameClass对象使用完全相同的映射,请将其设为静态变量。

答案 1 :(得分:1)

正如许多评论者所建议的那样,常量全局变量没有任何问题。如果Globals是可变的,它们只是问题。既然你说数据永远不会改变,那么只需将它们变成const全局变量即可。但是,由于它们具有复杂的构造函数,如果它们不是函数局部静态函数,则会遇到static initialization order fiasco。因此修复程序如下所示:

File1:

const map<string, string>& amap() {
    static const map<string,string> v {
        {"something", "nothing"},
        {"key", "value"},
    };
    return v;
}

File2(或者标题)

const map<string, string>& amap();

答案 2 :(得分:0)

您的地图似乎包含一种配置数据。我理解:

  • 你只有一张地图在任何地方都可以使用,但它到处都包含相同的日期
  • 你的地图不是常数,所以应该可以改变它(或者在启动时加载它)。

我建议您使用简单的dbconfig类来解决第一个问题:

class dbconfig {
    static map<string, string> amap;  // satic: there's only one of it
public: 
    operator const map<string,string>& () const  
    { return amap; } 
    // may be some functions to maintain the map 
}; 
map<string, string> dbconfig::amap{   // there's only one such map 
        {"something", "nothing"},     // and it's only viisble in dbconfig
        {"key", "value"},             // so totally protected
    };

诀窍是使用转换运算符,它只返回一个只读常量。所以你可以在程序的任何地方使用它,就像:

dbconfig cfg;   // local variable.  You don't have to worry about it
SameClass sc{ cfg };   // it whill be automatically converted in a reference to
                       // your single static map.  

优点是您的配置确实封装在对象中。因此,您可以定义一些成员来管理您的地图(添加或删除键)。

由于地图不是直接对外部可见,而是仅通过操作员,因此您可以让dbconfig对象的内部管理发展,而无需使用它来更改代码。例如,您可以在程序启动时将地图保持为空,并在第一次请求时从配置文件或其他任何内容加载数据。

然而,有一个重要的开放性问题:每个使用对象是否都有自己的地图副本,还是应该引用单个dbconfig地图?

其他说法:您是否设想动态更改地图内容,并希望所有对象都使用最新版本?

根据答案,您可以定义用户类以保留自己的地图副本:

class SameClass {
    map<string, string> mine;
public:
    SameClass (const map<string, string>& m) : mine(m) { // const ref, but local copy
    ... 
    }; 

或继续使用参考:

class SameClass {
    const map<string, string> & mine; // refers to the original. No own copy
public:
    SameClass (const map<string, string>& m) : mine(m) { // const ref   ... 
    }; 
};

答案 3 :(得分:0)

经过一周的尝试,我终于解决了这个问题!

感谢所有回答的人,我根据他们的想法找到问题的解决方案。

我创建一个新的头文件并将其命名为SetMap.hpp,这里是代码:

#ifndef SETMAP_HPP
#define SETMAP_HPP

#include <map>
#include <string>

struct SetMap
{
    const std::map<std::string, std::string> mymap{
        {"KEY_HERE","VALUE_HERE"},
    };
};

#endif // SETMAP_HPP

然后,只要我需要在程序中并初始化结构,我就会包含此标题:

#include "SetMap.hpp"

SetMap sm;
// use as sm.mymap;
SameClass sx{sm.mymap};

SameClass的构造函数接受const映射引用,如下所示:

SameClass (const map<string, string> &m);

当我需要编辑键或值时(因为这个地图就像数据库一样,在我的程序中),我只需要在一个地方编辑标题SetMap.hpp。

这样,就没有使用全局变量,因为变量&#39; mymap&#39;在结构的范围内。

这里不需要类,因为对象很小,默认情况下结构的变量是公共的。此外,如果需要添加相同&#34;概念的其他变量&#34; - 定义并声明一次 - 在需要时使用,只需将其添加到结构中。

感谢所有花时间帮助我的人!