gpt4 book ai didi

c++ - "Dynamic"没有模板或向下转换的参数类型(?)

转载 作者:行者123 更新时间:2023-11-30 03:43:58 25 4
gpt4 key购买 nike

我有我的 fancyFunction它采用一组元素实现接口(interface) A .该函数根据通过接口(interface)读取的属性对这些元素进行复杂的分析 A .在此分析过程中,它将调用 Consumer c 的方法。它将元素作为参数。

Consumer旨在采用与 A 完全无关的特定类型的参数.

你可以想象 A是图中边的抽象。该图在 fancyFunction 中进行了分析并且 - 例如 - 每次函数“越过”一条边时,它都会将该边发送到 Consumer它打印存储在边缘中的附加信息,这些信息与它是边缘无关。

下面给出的代码当然不会用类型化语言(尤其是 C++)编译,但如果不考虑类型(Matlab、Python),代码就可以运行。

要使其在类型化语言(尤其是 C++)中工作,我看到两个选项:

  1. 将函数声明为

    template <class CONSUMER>
    void fancyFunction(A[] setOfAs, CONSUMER c){ ... }

  2. 声明operation1operation2获取最一般的对象,然后在实现中进行向下转换。

在这种情况下您建议做什么?(据我所知,访问者模式不是一个选项。)

完整代码大纲(我有一段时间没有使用C++,所以如果有小的语法错误请原谅。):

void fancyFunction(A[] setOfAs, Consumer* c){
// do fancy analysis of setOfAs by properties
// read through interface A

double x = setOfAs[i]->getX();

// call functions in c with arguments of setOfAs[j]
...
c->operationX(setOfAs[i]);
...
c->operationY(setOfAs[j]);
...
}

class A{
virtual double getX();
}

class Consumer{
virtual void operationX(??? x); // whoops, what type do we expect?
virtual void operationY(??? y); // whoops, what type do we expect?
}

class Consumer1{
void operationX(Obj1 x){ ... } // whoops, override with different type
void operationY(Obj1 y){ ... } // whoops, override with different type
}

class Consumer2{
void operationX(Obj2 x){ ... } // whoops, override with different type
void operationY(Obj2 y){ ... } // whoops, override with different type
}

class Obj1 : public A {};
class Obj2 : public A {};

void test(){

Obj1 o1[];
Obj2 o2[];

Callback1 c1;
Callback2 c2;

fancyFunction(o1, &c1);
fancyFunction(o2, &c2);
}

最佳答案

我相信您正在寻找的解决方案称为 Visitor Pattern .

您不想在您喜欢的函数中手动转换对象 A 的每个实例,因为那是一场维护噩梦,而且代码味道很明显

另一方面,如果每个对象自动处理自己的转换会怎样?这就是访问者模式。

您首先在基类 (A) 中定义一个新的“访问”函数,将您的 Consumer 作为其唯一参数:

class A
{
public:
virtual void Visit(Consumer& consumer) = 0;
}

然后您为每个继承的类实现此函数,因此:

class B : public A
{
public:
void Visit(Consumer& consumer)
{
consumer.DoOperation(this); // 'this' utomatically resolves to type B*
}
}

每个派生类型现在通过将“this”指针传递给提供的消费者实例来处理调用适当的操作重载。 “this”指针被自动解释为可能的最具体类型。

回顾您的原始示例代码,您似乎让每个 Consumer 提供多个操作,并且只处理一个类型。 模式可能需要您稍微更改此范例:为每个操作创建一个消费者,其中每个消费者为继承的每个可能提供重载类型。

class ConsumerX
{
public:
void DoOperation(A* a) { /* ERROR! This is a base type. If this function is called, you probably need to implement another overload. */ }
void DoOperation(B* b) { /* Much better */ }
}

class ConsumerY
{
public:
void DoOperation(A* a) { /* ERROR! This is a base type. If this function is called, you probably need to implement another overload. */ }
void DoOperation(B* b) { /* Much better */ }
}

然后你的实现循环看起来像这样:

ConsumerX consumerX; // Does Operation X for every type
ConsumerY consumerY; // Does Operation Y for every type
for(int x = 0; x < numElements, x++)
{
auto element = setOfAs[x];
element.Visit(consumerX); //Do operation X
element.Visit(consumerY); //Do operation Y
}

关于c++ - "Dynamic"没有模板或向下转换的参数类型(?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35795188/

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