这个问题(松散地)与我昨天在这里提出的问题有关.
我刚刚重构了一个容器类(Ecosystem),它包含指向Individuals的指针:
class Ecosystem
{
// This is an interface class providing access
// to functions in Individual without exposing
// the Individual class.
// It performs global operations on the entire ecosystem
// (like sorting individuals based on certain criteria)
// but is also capable of invoking functions from the
// Individual class.
// It also holds the global configuration for this ecosystem.
private:
Config config;
std::map<int, std::shared_ptr<Individual> > individuals;
public:
Ecosystem() {};
void sort_individuals();
void func1(int _individual_id)
{
individuals[_individual_id]->func1(config);
}
void func2(int _individual_id)
{
individuals[_individual_id]->func2(config);
}
// etc...
};
class Individual
{
private:
public:
Individual() {};
void func1(const Config& _config)
{
// Operations using _config.param_1, _config.param_2, ...
}
void func2(const Config& _config)
{
// Operations using _config.param_n, _config.param_m, ...
}
// etc...
}
Run Code Online (Sandbox Code Playgroud)
我现在处于这样的情况,我必须通过config几乎每个函数调用Individual对象.最初我想,好吧,我只是做一个static Config config;内部Individual,但很快我意识到我需要能够创建具有不同配置的多个共存生态系统.
如果我理解static正确的含义,如果我static Config config;在Individual其中分配了configfrom 的值Ecosystem,那么每次我创建一个新的生态系统时它都会被覆盖.
我的问题是:有没有办法将config 一次传递给Individual类而不使其为静态,以避免将其作为每个函数的参数传递?
我曾考虑有Config* config两个Ecosystem和Individual,但是这意味着每个人都会有一个指向配置对象,这似乎是笨重.我需要的是等效的静态成员,其范围可以识别容器层次结构,如果这有意义的话.
一旦创建,Config对象将不会被更改,因此可以有一个const Config config;.
提前感谢您的任何建议!
编辑1
谢谢大家的回复.马修克劳斯有一个观点,我在原始问题中没有提供我的生态系统类的正确构造函数,当然,这是对我的疏忽.我现在看到它可能是相关的,但我更专注于说明我所追求的变量访问类型而不是我的类的外观,所以我提出了一个简单的例子.如果我用额外的评论引起讨论的混乱,我会道歉!
这里提出的解决方案都非常好,但我可以从答案中看出,C++没有任何方法来定义这样的类级变量而不将它们定义为static.我需要的是一个类级变量,其范围仅限于其容器.这只是我的想法的一个例子,它不会编译(我现在肯定这不能在C++中完成):
class Ecosystem
{
// This is an interface class providing access
// to functions in Individual without exposing
// the Individual class.
// It performs global operations on the entire ecosystem
// (like sorting individuals based on certain criteria)
// but is also capable of invoking functions from the
// Individual class.
// It also holds the global configuration for this ecosystem.
private:
Config config;
std::map<int, std::shared_ptr<Individual> > individuals;
public:
Ecosystem(const std::string& _file_name)
{
Config cfg(_file_name);
config = cfg;
// This is done before any Individual objects are created.
Individual::set_config(cfg);
for (int i = 1; i <= 10; ++i)
{
individuals[i] = std::make_shared<Individual>();
}
};
void sort_individuals();
void func1(int _individual_id)
{
individuals[_individual_id]->func1();
}
void func2(int _individual_id)
{
individuals[_individual_id]->func2();
}
// etc...
};
class Individual
{
private:
// v--- No such thing!
scoped static Config config;
public:
Individual() {};
void func1()
{
// Operations using config.param_1, config.param_2, ...
}
void func2()
{
// Operations using config.param_n, config.param_m, ...
}
// v--- No such thing!
scoped static void set_config(const Config& _config)
{
config = _config;
}
// etc...
}
int main(int argc, char* argv[])
{
Ecosystem ecosystem1("config_file1.txt");
Ecosystem ecosystem2("config_file2.txt");
// Conduct experiments with the two ecosytems.
// Note that when ecosystem2 is created, the line
//
// Individual::set_config(cfg);
//
// should *not* overwrite the class-level variable
// config set when ecosystem1 was created.
// Instead, it should create a
// class-level variable but limited to the scope of ecosystem 2.
// This operates on Individual 1 in ecosystem 1
// with the parameters set in config_file1.txt
ecosystem1->func1(1);
// This operates on Individual 1 in ecosystem 2
// with the parameters set in config_file2.txt
ecosystem2->func1(1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我将建议在构造时将指针传递给每个人.这会浪费空间,但应该是最容易维护的解决方案.
再次感谢大家的意见,如果问题令人困惑,请道歉.
如果我理解正确,将配置传递给an的构造函数Individual应该:
class Individual {
const Config& config_;
public:
Individual(const Config& c) : config_(c) {}
void func1() {
// use config_
}
};
Run Code Online (Sandbox Code Playgroud)
你仍然需要传递Config给每个单独的构造函数,但这只是一个单点,而不是许多函数Individual都有.此外,Individual如果您觉得创建过于繁琐,您可以将创建封装到工厂方法中.