如何在程序中声明/定义一次并在两个类中使用映射列表

How to declare / define once and use map list in two classes in program?

本文关键字:两个 列表 映射 声明 程序 定义 一次      更新时间:2023-10-16

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

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

// 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<>中并返回地图?

我不想使用全局变量!

如果你想在程序中使用你的变量WHREVER,我们谈论的是全局变量,你不想使用它(这很好!)。

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

class Variables
{
private:
Variables () {} // to prevent instantiation, which makes no sense
public:
static map<string , int> myMap;
static float numba;
};
float Variables::numba = 0;
map<string , int> Variables::myMap = map<string, int>;
//somehow initialize your static variables

你像这样使用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
}

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

正如许多评论者所建议的,常量全局变量没有错。全局变量只有在可变的情况下才是问题。既然你说数据永远不会改变,那就简单地把它们变成const全局变量。然而,由于它们有复杂的构造函数,如果它们不是函数局部静态,则会遇到静态初始化顺序的惨败。所以修复程序看起来是这样的:

文件1:

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

File2(或者可能是标头)

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

您的映射似乎包含一种配置数据。我知道:

  • 你只有一张到处都用的地图,但它到处都包含相同的日期
  • 您的映射不是恒定的,所以应该可以以某种方式更改它(或在启动时加载它)

我建议您使用简单的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地图?

Otherhise表示:您是否打算动态更改地图内容,并希望所有对象都使用最新版本?

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

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

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

感谢所有回答的人,在这里,我根据他们的想法解决了我的问题。

我创建了一个新的头文件,并将其命名为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.

这样,就不需要使用全局变量,因为变量"mymap"在结构的作用域中。

这里不需要类,因为对象很小,默认情况下结构的变量是公共的。此外,如果需要添加其他具有相同"概念"(定义并声明一次)的变量,只要将其添加到结构中即可。

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