gpt4 book ai didi

c++ - 多重继承 : calling all the overriden functions

转载 作者:行者123 更新时间:2023-11-28 04:22:21 25 4
gpt4 key购买 nike

我有几个我希望类具有的行为。我想隔离这些行为,以便我可以重用该代码,随意混合搭配。

例如,执行此操作的一种方法是:

class BehaviorAbstract {
protected:
virtual void processInfo(Info i) = 0;
}

class Behavior1: public BehaviorAbstract {
protected:
virtual void processInfo(Info i) { ... }
void performBehavior1() { ... }
}

class Behavior2: public BehaviorAbstract {
protected:
virtual void processInfo(Info i) { ... }
void performBehavior2() { ... }
}

class ConcreteObject: public Behavior1, Behavior2 {
protected:
void processInfo(Info i) {
// needs to call processInfo of Behavior1 and Behavior2
Behavior1::processInfo(i);
Behavior2::processInfo(i);
}
void perform() {
this->performBehavior1(); this->performBehavior2();
}
}

所以问题的关键在于:ConcreteObject 需要调用它继承的所有类的 2 个函数 processInfo(相同的名称,相同的参数)。想象一下,所有的行为类都是由不同的开发人员编写的。该函数必须具有相同的名称,因为它们都派生自 BehaviorAbstract。

执行此操作的合理设计模式是什么?我怀疑多重继承在这里可能是错误的,也许“多重组合”会更好,但我需要所有 Behavior 类和 ConcreteObject 派生自 BehaviorAbstract,它们都需要对 BehaviorAbstract 的同一个 protected 数据成员进行操作。

我上面写的解决方案感觉不对而且丑陋。有没有一种方法可以自动调用所有实现 processInfo 的父类,而不必明确地重写它们的名称?

非常感谢您的帮助。

最佳答案

如果我没猜错,那么这个问题就是关于重构 ConcreteObject 类。

方法 #1:

如果您可以使 performBehavior() 成为 BehaviorAbstract 基类的一部分,那么您可以简单地使用 BehaviorAbstract* 的 vector 并让多态性做它的事情。我认为这可以看作是策略模式。

#include <iostream>
#include <vector>

typedef int Info;

struct BehaviorAbstract
{
virtual void processInfo(Info i) = 0;
virtual void performBehavior() = 0;
};

struct Behavior1 : BehaviorAbstract
{
void processInfo(Info i) override
{ std::cout<< "Behavior1::processInfo()" <<std::endl; }

void performBehavior() override
{ std::cout<< "Behavior1::performBehavior()" <<std::endl; }
};

struct Behavior2 : BehaviorAbstract
{
void processInfo(Info i) override
{ std::cout<< "Behavior2::processInfo()" <<std::endl; }

void performBehavior() override
{ std::cout<< "Behavior2::performBehavior()" <<std::endl; }
};

//------------------------------------------------//

struct ConcreteObject
{
typedef std::vector<BehaviorAbstract*> vec_behavior;

vec_behavior vba;

ConcreteObject(vec_behavior &&v) : vba(v)
{;}

void processInfo(Info i)
{
for (auto &&itr : vba)
itr->processInfo(i);
}

void perform()
{
for (auto &&itr : vba)
itr->performBehavior();
}
};

int main()
{
ConcreteObject foo = {{new Behavior1(), new Behavior2()}};
foo.processInfo(23);
foo.perform();
}

示例:https://rextester.com/UXR42210

方法 #2:

使用创建元组的可变参数模板。迭代该元组并运行函数。同样,如果 performBehavior1()performBehavior2() 可以共享相同的函数名称,那么它会变得更容易。这里的额外复杂性是您需要编写一种手动迭代该元组的方法。为简单起见,我直接从 iterate_tuple 结构调用了 processInfo()

#include <iostream>
#include <tuple>

typedef int Info;

struct BehaviorAbstract
{
virtual void processInfo(Info i) = 0;
};

struct Behavior1 : BehaviorAbstract
{
void processInfo(Info i) override
{ std::cout<< "Behavior1::processInfo()" <<std::endl; }

void performBehavior1()
{ std::cout<< "Behavior1::performBehavior1()" <<std::endl; }
};

struct Behavior2 : BehaviorAbstract
{
void processInfo(Info i) override
{ std::cout<< "Behavior2::processInfo()" <<std::endl; }

void performBehavior2()
{ std::cout<< "Behavior2::performBehavior2()" <<std::endl; }
};


//------------------------------------------------//

template<typename T, std::size_t N>
struct iterate_tuple
{
static void run(T &t, Info i)
{
std::get<N>(t).processInfo(i);
iterate_tuple<T, N-1>::run(t,i);
}
};

template<typename T>
struct iterate_tuple<T, 0>
{
static void run(T &t, Info i)
{
std::get<0>(t).processInfo(i);
}
};

//------------------------------------------------//

template<typename ...T>
struct ConcreteObject
{
std::tuple<T ...> tmp;
static constexpr std::size_t tuple_size = std::tuple_size<decltype(tmp)>::value;

ConcreteObject() : tmp{std::forward<T>(T()) ...}
{;}

void processInfo(Info i)
{
iterate_tuple<decltype(tmp), tuple_size-1>::run(tmp, i);
}

void perform()
{
std::get<0>(tmp).performBehavior1();
std::get<1>(tmp).performBehavior2();
}
};


int main()
{
ConcreteObject<Behavior1,Behavior2> foo;
foo.processInfo(23);
foo.perform();
}

示例:https://rextester.com/SBRE16218

这两种方法都避免了多重继承,据我所知,这是你想要避免的。仅供引用,越简单越好。

关于c++ - 多重继承 : calling all the overriden functions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55171127/

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