C++:多个策略相互调用

发布于 2024-12-18 21:50:29 字数 760 浏览 2 评论 0 原文

对于基于策略的类设计,我需要一些策略来调用在其他策略中找到的函数:

struct PolicyA {
  void foo() {
    // ...
  }
};

struct PolicyB {
  void bar() {
    // Need to call foo() here
  }
};

template <class A, class B> MyClass : A, B {};

我看到的两个选项是:

  • MyClass 传递给 PolicyA PolicyB 作为模板参数,并执行类似 dynamic_cast*>(this)->foo(); 的操作。然而,这很容易变得非常复杂(特别是如果不仅 B 调用 A 而且还有其他方式)。
  • 每个策略都有一个基类,其中所有函数都声明为纯虚函数。当函数之一需要自己的模板参数时,此操作会失败,因为虚拟模板函数是不可能的。

这应该是一个常见问题,但我没有发现任何问题。我猜想可能有某种增强魔法之类的东西。你会如何解决这个问题?

编辑:另请参阅此处的后续内容。

For a policy-based class-design I need some of the policies to call functions that are found in other policies:

struct PolicyA {
  void foo() {
    // ...
  }
};

struct PolicyB {
  void bar() {
    // Need to call foo() here
  }
};

template <class A, class B> MyClass : A, B {};

The two options I see are:

  • Pass MyClass<A, B> to PolicyA and PolicyB as template parameters and do something like dynamic_cast<MyClass<A, B>*>(this)->foo();. However this may easily get very complicated (especially if it's not only B calling A but also the other way).
  • Have a base class for each policy where all the functions are declared as pure virtual. This fails when one of the function needs its own template parameters, since virtual template functions are not possible.

This should be a common problem, but I didn't find anything. I guess there probably is some boost-magic or something. How would you solve this?

Edit: See also the followup here.

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

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

发布评论

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

评论(1

这个俗人 2024-12-25 21:50:29

为什么 PolicyB 不封装 PolicyA 并根据需要调用它? PolicyB 显然知道 PolicyA - 不需要基类或继承。

似乎您的所有 Policy 实现都有一些外部调用者可以同意的通用 apply 方法?

编辑:

是的,所以如果这不仅仅是一个特定策略实现需要访问另一个策略实现的简单情况,您可能应该专注于为Policy创建一个接口 - 甚至可能一个 Rule 类,可以组合在一起形成特定的 Policy - 请参阅规范模式。

class Rule {
    allows(Foo foo);
}

class Policy {
    Rule rule = new NotNullRule().and(someOtherRule);

    void applyTo(Foo foo) {
        if (rule.allows(foo)) {
            return foo;
        }
        foo.disable();
    }
}

随意称呼它们,ConditionRuleSpecification - 它们对于以一种不需要的方式将逻辑片段组装在一起很有用。依赖他们。然后,当有人查看 PolicyA 时,他们可以清楚地看到控制其行为的规则/条件(客观化)。

一旦您实现了策略,如果您需要对某些内容强制执行多个策略,您可以再次使用复合模式,以便外部类只能看到 Policy 接口。但同样,您有一个明确的“命名”策略被引用,而不仅仅是交叉调用函数。

Why doesn't PolicyB encapsulate PolicyA and call it as it needs? PolicyB is obviously aware of PolicyA - no need for base classes or inheritance.

It seems like all of your Policy implementations have some common apply method that outside callers can agree upon?

Edit:

Right, so if it's not just a simple case of one particular Policy implementation needing access to another, you should probably focus on creating a single interface for Policy - perhaps even a Rule class that can be composed together to form a particular Policy - see the Specification pattern.

class Rule {
    allows(Foo foo);
}

class Policy {
    Rule rule = new NotNullRule().and(someOtherRule);

    void applyTo(Foo foo) {
        if (rule.allows(foo)) {
            return foo;
        }
        foo.disable();
    }
}

Call them whatever you want, Condition, Rule, Specification - they're useful for assembling pieces of logic together in a manner that doesn't depend on them. Then when someone is looking at PolicyA they can see, clearly, the rules/conditions that govern its behavior, objectified.

Once you have policy implementations in place, if you need to enforce several policies on something, you can use the composite pattern again so that external classes only see a Policy interface. But again, you have a clear 'named' policies that are being referred to, not just cross-calling functions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文