在不知道完整层次结构的情况下进行双重调度

发布于 2024-11-01 10:34:46 字数 1307 浏览 5 评论 0原文

我想在 C++ 中实现以下内容:

我想要一个类的一堆子类,能够调用一个接受任何这些类型的一对对象的函数。应该有一个为混合类型或基本类型调用的通用实现,以及如果两个相同派生类型的对象被调用的专用实现。用作参数

据我所知,这是双重调度的经典应用。但是,我有以下限制:

必须能够从现有类派生新类,并为这些新类添加新的配对函数而不更改现有类,例如在外部库中。

我在我的最后一个问题中提出的方法是错误的,并且提出的解决方案仅适用于编写基类时已知的类型。

关于如何实施这个有什么建议吗?这可能吗?

更新:代码说了一千多个字。以下方法有效:

#include <iostream>

class B;

class A
{
public:
  virtual void PostCompose(A* other)
    {
      other->PreCompose(this);
    }
  virtual void PreCompose(A* other)
    {
      std::cout << "Precomposing with an A object" << std::endl;
    }
  virtual void PreCompose(B* other);
};

class B : public A
{
public:
  using A::PreCompose;
  virtual void PostCompose(A* other)
    {
      other->PreCompose(this);
    }
  virtual void PostCompose(B* other)
    {
      other->PreCompose(this);
    }
  virtual void PreCompose(B* other)
    {
      std::cout << "Precomposing with a B object" << std::endl;
    }
};

void A::PreCompose(B* other)
  {
    PreCompose((A*)other);
  }

int main()
{
  B b;
  A* p = &b;
  p->PostCompose(p); // -> "Precomposing with a B object"
}

但在实现 A 时需要了解 B。有更好的办法吗?

I would like to implement the following thing in C++:

I would like to have a bunch of child classes of a single class with the ability to call a function that takes a pair of objects of any of these types. There is supposed to be a generic implementation that is called for mixed types or the base type and specialised implementations which get called if two objects of the same derived type are used as arguments.

As far as I know, this is a classic application of double dispatch. However, I have the following constraint:

It must be possible to derive new classes from the existing ones and add new pair-functions for these new classes without changing existing classes, for instance in an external library..

The approach I proposed in my last question is faulty, and the solution proposed there only works for types that are known at the time when the base class is written.

Any suggestion on how to implement this? Is that even possible?

Update: Code says more than a thousand words. The following approach works:

#include <iostream>

class B;

class A
{
public:
  virtual void PostCompose(A* other)
    {
      other->PreCompose(this);
    }
  virtual void PreCompose(A* other)
    {
      std::cout << "Precomposing with an A object" << std::endl;
    }
  virtual void PreCompose(B* other);
};

class B : public A
{
public:
  using A::PreCompose;
  virtual void PostCompose(A* other)
    {
      other->PreCompose(this);
    }
  virtual void PostCompose(B* other)
    {
      other->PreCompose(this);
    }
  virtual void PreCompose(B* other)
    {
      std::cout << "Precomposing with a B object" << std::endl;
    }
};

void A::PreCompose(B* other)
  {
    PreCompose((A*)other);
  }

int main()
{
  B b;
  A* p = &b;
  p->PostCompose(p); // -> "Precomposing with a B object"
}

but it requires knowledge of B when implementing A. Is there a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

黑寡妇 2024-11-08 10:34:46

由于派生类只需要检测参数类型是否与对象类型匹配,因此您可以使用简单的检查。

virtual void foo( base *argument_base ) {
    if ( derived *argument = dynamic_cast< derived * >( argument_base ) ) {
        argument->something = pair_match_foo;
    } else {
        base_class::foo( argument_base );
    }
}

Since the derived classes only need to detect if the parameter type matches the object type, you can just use a straightforward check.

virtual void foo( base *argument_base ) {
    if ( derived *argument = dynamic_cast< derived * >( argument_base ) ) {
        argument->something = pair_match_foo;
    } else {
        base_class::foo( argument_base );
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文