gpt4 book ai didi

c++ - 访问聚合器类中类之间共享的变量

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:17:08 25 4
gpt4 key购买 nike

我手头有一个问题,需要针对不同的算法进行非常模块化的设计。例如基于种群的优化算法,如遗传算法、粒子群算法等。这些算法有多种变体,因此我计划将较小的构建 block 作为抽象类,并让特定的构建 block 插入。

例如假设我们有 algo1,它可以分为以下子程序

algo1
loop
{
sub1 ()
sub2 ()
sub3 ()
}

为此,我可以创建三个接口(interface),实现将根据它们的实现覆盖这些接口(interface)。因此

//Sub1Class, Sub2Class, Sub3Class are interfaces/abstract classes
class algo1
{
sub1Class *sub1Obj;
sub2Class *sub2Obj;
sub3Class *sub3Obj;
}

// constructor or setter method to set the implementation
algo1 (Sub1Class *myAlgo1Obj, Sub2Class myAlgo1Obj, Sub3Class myAlgo1Obj)
{
sub1Obj = myAlgo1Obj;
sub2Obj = myAlgo2Obj;
sub3Obj = myAlgo3Obj;
}

doAlgo1
{
loop
{
sub1Obj->algo ();
sub2Obj->algo ();
sub3Obj->algo ();
}
}

这可以做到,但所有算法都使用 algo 类的属性,并且算法共享中间变量,我不想提供 getter/setter。

我的问题是可以使用哪些技术来管理算法之间共享的中间变量。我可以将它作为算法方法实现参数传递,但是中间体的数量和类型可能会从一个实现变为另一个实现。在那种情况下,创建一个单独的临时变量类或在 cpp 中创建类似 friend 的东西是个好主意吗?请注意,中间结果可以是大型 vector 和矩阵。

如果您需要更多信息或说明,请告诉我。

注意:我可以通过引入局部变量和重新计算来省略算法之间共享的变量,但是算法是迭代的并且涉及大型矩阵的计算密集型,因此我希望尽可能减少对象的创建和销毁。

最佳答案

我可以建议使用反向控制容器来解决您的问题。

首先你应该创建几个抽象类来将它保存在容器中:

class ISubroutineState {
public:
ISubroutineState() = default;

virtual int getVar1() const = 0;
virtual void setVar1(int v1) = 0;
};

class ISubroutineState1 : public ISubroutineState {
public:

virtual std::string getVar2() const = 0;
virtual void setVar2(std::string& v2) = 0;
};

子程序状态类实现示例:

class SubState1 : public ISubroutineState1 {
int var1;
std::string var2;

public:
int getVar1() const {
return var1;
}

std::string getVar2() const {
return var2;
}

void setVar1(int v1) { var1 = v1; }
void setVar2(std::string& v) { var2 = v; }
};

IoC 容器(请注意它可以以任何允许的方式访问 - 为简单起见,我只使用静态指针):

class StateBroker
{
std::map<const char*, ISubroutineState*> *storage;
public:
StateBroker();

template <class S>
void StateBroker::bind(S* state) {
storage->emplace(typeid(S).name(), state);
}

template <class S>
S* StateBroker::get() const {
auto found = storage->find(typeid(S).name());
if (found == storage->end()) return NULL;
return (S*)found->second;
}

~StateBroker();
};

StateBroker* stateBroker;

现在您可以实现任何类型的子例程:

 class ISubroutine {
public:
virtual void Execute() = 0;
};

class Sub1Class : public ISubroutine {
public:
void Execute()
{
if (stateBroker == NULL)
{
std::cout << "Sub1 called" << std::endl;
}
else {
ISubroutineState1* ss1 = stateBroker->get<ISubroutineState1>();
std::cout << "Sub1 with state called" << std::endl;
ss1->setVar1(1);
ss1->setVar2(std::string("State is changed by Sub1Class"));
std::cout << *static_cast<SubState1*>(ss1) << std::endl;
}
}
};

class Sub2Class : public ISubroutine {
public:
void Execute()
{
if (stateBroker == NULL)
{
std::cout << "Sub2 called" << std::endl;
}
else {
ISubroutineState* ss1 = stateBroker->get<ISubroutineState>();
std::cout << "Sub2 with state called" << std::endl;
ss1->setVar1(2);
std::cout << *static_cast<SubState1*>(ss1) << std::endl;
}
}
};

class Sub3Class : public ISubroutine {
public:
void Execute()
{
if (stateBroker == NULL)
{
std::cout << "Sub3 called" << std::endl;
}
else {
ISubroutineState1* ss1 = stateBroker->get<ISubroutineState1>();
std::cout << "Sub3 with state called" << std::endl;
ss1->setVar1(3);
ss1->setVar2(std::string("State is changed by Sub3Class"));
std::cout << *static_cast<SubState1*>(ss1) << std::endl;
}
}
};

另请注意,子例程的 Execute() 可以请求执行其任务所需的任何类型的子例程状态。它甚至可以创建额外的状态实例(例如,用于算法的后期阶段)。

现在主要算法如下所示:

class Algo {
private:
Sub1Class* sub1;
Sub2Class* sub2;
Sub3Class* sub3;

public:
Algo(Sub1Class* s1, Sub2Class* s2, Sub3Class* s3) : sub1(s1), sub2(s2), sub3(s3){}

void Execute()
{
sub1->Execute();
sub2->Execute();
sub3->Execute();
}
};

...及其用法(请注意,根据 StateBroker 是否已初始化,它可以用作无状态的和有状态的)

Sub1Class s1;
Sub2Class s2;
Sub3Class s3;
std::cout << "Stateless algorithm" << std::endl;
Algo mainAlgo(&s1, &s2, &s3);
mainAlgo.Execute();

stateBroker = new StateBroker();
SubState1* state = new SubState1();
stateBroker->bind<ISubroutineState>(state);
stateBroker->bind<ISubroutineState1>(state);

std::cout << "Statefull algorithm" << std::endl;
Algo statefulAlgo(&s1, &s2, &s3);
statefulAlgo.Execute();

请注意,Algo 类对子程序状态、状态代理等一无所知; Sub2Class 不知道 ISubroutineState1; StateBroker 不关心状态和子程序的实现。

顺便说一句,您可以在 https://github.com/ohnefuenfter/cppRestudy 查看示例项目(VS2015)

关于c++ - 访问聚合器类中类之间共享的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27225945/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com