这个问题(松散地)与我昨天here提出的问题有关。
我刚刚重构了一个容器类(Ecosystem
),其中包含指向Individual
的指针:
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...
}
我现在处于这样的情况:我必须通过config
几乎每个函数调用Individual
个对象。最初我想,好吧,我只是在static Config config;
内Individual
,但很快我意识到我需要能够创建多个具有不同配置的共存生态系统。
如果我正确理解了static
的含义,如果我static Config config;
Individual
内的config
被Ecosystem
分配了config
,那么每次我创建一个新的生态系统时都会被覆盖。
我的问题是:有没有办法将Config* config
一次传递给个人类,而不会将其设为静态,以避免将其作为参数传递每个功能?
我考虑在Ecosystem
和Individual
中都有const Config config;
,但这意味着每个人都会有一个指向配置对象的指针,这似乎很笨拙。我需要的是等效的静态成员,其范围可以识别容器层次结构,如果这有意义的话。
创建后,Config对象不会被更改,因此可以拥有static
。
提前感谢您的任何建议!
编辑1
感谢大家的回复。 Matthew Kraus指出,我在原始问题中没有为我的生态系统课提供正确的构造函数,这当然是对我的疏忽。我现在看到它可能是相关的,但我更专注于说明我之后的变量访问类型而不是我的类看起来像什么,所以我提出了一个简单的例子。如果我用额外的评论引起讨论混乱,请道歉!
这里提出的解决方案都非常好,但我可以从答案中看出,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;
}
。我需要的是一个类级变量,其范围仅限于其容器。这只是我的想法的一个例子,它不会编译(我现在肯定这不能在C ++中完成):
File->settings->Keymap and select 'eclipse' from keymap dropdown.
我将建议在构造时将指针传递给每个人。这会浪费空间,但应该是最容易维护的解决方案。
再次感谢大家的意见,如果问题令人困惑,请道歉。
答案 0 :(得分:6)
如果我理解正确,将配置传递给Individual
的构造函数应该:
class Individual {
const Config& config_;
public:
Individual(const Config& c) : config_(c) {}
void func1() {
// use config_
}
};
您仍然需要将Config
传递给每个单独的构造函数,但这只是一个单点,而不是Individual
会有多少函数。此外,如果您觉得创建过于繁琐,可以将Individual
的创建封装到工厂方法中。
答案 1 :(得分:2)
如果Individual
个对象不应包含配置,则总是
class ConfiguredIndividualReference
{
private:
std::shared_ptr<Individal> ptr; // or just Individual* depending on how you use this
const Config &config;
public:
// ...
void func1()
{
ptr->func1(config);
}
// ...
};
此外,您可以创建一个成员函数来自动生成它:
ConfiguredIndividualReference fetch(int id) const {
return ConfiguredIndividualReference(individuals[id], config);
}
并且总是使用它来获取个人而不是直接访问地图。
答案 2 :(得分:1)
在我制定解决方案的过程中,有几个答案正在流传,但我还是认为我还是会发布我的答案。这是一个完整的解决方案,可以在上下文中查看所有内容:
#include <iostream>
#include <string>
#include <map>
class Config
{
public:
explicit Config(std::string name) : name(name) {}
std::string getName() const { return name; }
private:
std::string name;
};
class Individual
{
public:
// using 'explicit' ensures that an Individual is created with a Config
explicit Individual(const Config& config) :
config(config) {}
std::string getConfigName() const { return config.getName(); }
void func1() {}
void func2() {}
private:
// a "const reference" is read-only
const Config& config;
};
// notice that the dependency on Config is removed from Ecosystem
class Ecosystem
{
private:
// std::map<int, std::shared_ptr<Individual> > individuals;
// I compiled using Individual*, so be aware
// of the implications of using a naked ptr vs shared_ptr
std::map<int, Individual*> individuals
public:
Ecosystem() {};
void sort_individuals();
void func1(int _individual_id)
{
// no dependency on Config
individuals[_individual_id]->func1();
}
void func2(int _individual_id)
{
individuals[_individual_id]->func2();
}
};
int main()
{
using namespace std;
Config globalConfig("global configuration");
Config localConfig("local configuration");
// the Config object passed to an Individual must
// last the lifetime of the Individual
Individual individualA(globalConfig);
Individual individualB(localConfig);
// the following prints "global configuration"
cout << "individualA config is: " << individualA.getConfigName() << endl;
// the following prints "local configuration"
cout << "individualB config is: " << individualB.getConfigName() << endl;
return 0;
}
如代码中所述,请确保Config
对象超出任何依赖于它的对象。像这样共享对象 - 即使您正在进行const引用 - 删除了物理依赖关系,但它并没有删除逻辑依赖关系。换句话说,C ++编译器可以在不知道Ecosystem
的情况下编译Config
类。但是,Ecosystem
取决于Individual
s,而Config
依赖于std::shared_ptr
s,因此需要预先警告。我的观点是const引用是vanilla C ++的方法,但如果管理Config
对象的生命周期是微不足道的话,那么值得考虑shared_ptr
。
修改强>
我编译时没有实际使用Individual*
;我在地图中使用了<div class="swiper-container" ng-show="menu()">
<div class="swiper-wrapper">
<div class="swiper-slide">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
<div class="swiper-slide">Slide 4</div>
<div class="swiper-slide">Slide 5</div>
<div class="swiper-slide">Slide 6</div>
<div class="swiper-slide">Slide 7</div>
<div class="swiper-slide">Slide 8</div>
<div class="swiper-slide">Slide 9</div>
<div class="swiper-slide">Slide 10</div>
</div>
<!-- Add Pagination -->
<div class="swiper-pagination"></div>
</div>
。请注意使用一个与另一个的含义。
答案 3 :(得分:1)
我发布了第二个答案,以满足每Config
个Ecosystem
而不是Individual
每个#include <iostream>
#include <string>
#include <map>
class Config
{
public:
explicit Config(std::string name) : name(name) {}
std::string getName() const { return name; }
private:
std::string name;
};
class Individual
{
public:
Individual() {}
void func1(const Config& config) const
{
std::cout << config.getName() << std::endl;
}
// you might remove the dependency of Config and
// just pass only the config parameters needed.
void func2(Type1 configParam1, Type2 configParam2) {}
};
// notice that the dependency on Config is removed from Ecosystem
class Ecosystem
{
public:
explicit Ecosystem(Config& config) : config(config) {}
void sort_individuals();
void func1(int _individual_id)
{
individuals[_individual_id]->func1(config);
}
private:
// std::map<int, std::shared_ptr<Individual> > individuals;
// I compiled using Individual*, so be aware
// of the implications of using a naked ptr vs shared_ptr
std::map<int, Individual*> individuals;
const Config& config;
};
int main()
{
using namespace std;
Config globalConfig("global configuration");
// Config objects don't need to be created in main();
// you could create them on the heap, too:
Config* localConfig = new Config("local configuration");
Ecosystem ecosystemA(globalConfig);
Ecosystem ecosystemB(*localConfig);
// TODO: add Individuals to each Ecosystem
// clean up objects on heap
delete localConfig;
return 0;
}
的新要求:
Config
我觉得我们已经回答了OP的原始问题&#34;有没有办法将config一次传递给Individual类而不使其静态,以避免将其作为参数传递每个功能&#34; 。此示例提供了更多选项。
此处的添加是在堆上创建Ecosystem(Config& config)
对象。这使得Config
的调用者负责管理main()
对象。同样,这不必在Config
中发生,但您可以修改我的示例以使用智能指针自动管理<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="IsChecked" Value="{Binding IsCheckedByDefault}"/>
<Setter Property="IsCheckable" Value="true"/>
<Setter Property="Header" Value="{Binding Title}"/>
</Style>
</ContextMenu.ItemContainerStyle>
个对象的生命周期。