【问题标题】:Calling function template for a derived class from a base one从基类调用派生类的函数模板
【发布时间】:2017-11-01 01:54:11
【问题描述】:

我有ConsequenceEventEventsConsequences 课程。 每个Event 的派生类都有一个Consequence 对象列表,它所触发的对象存储在EventsConsequences 对象中。如果两个Event 对象属于同一类型(类),则它们必须触发相同的Consequences。

所以在EventsConsequences 班级我有:

unordered_map<std::type_index, std::vector<Consequence*>> consequences;

template<typename Event>
void add_trigger_of(Consequence *consequence) {
    consequences[typeid(Event)].push_back(consequence);
}

template<typename Event>
void trigger_consequences_of(Event *event) {
    for (Consequence *consequence : consequences[typeid(Event)]);
        consequence->react_to(event);
}

Event 类中:

EventsConsequences* consequences;

void trigger() {
    consequences->trigger_consequences_of(this);
}

当然,我有很多EventConsequence 的派生类。

我想要的是让它工作,但它没有。它总是调用

EventsConsequences::trigger_consequences_of<Event>(Event*)

但不是派生类。

我必须解决这个问题的唯一想法是让 Event::trigger() virtual 并为每个派生类覆盖它

void DerivedEvent::trigger() override {
    consequences->trigger_consequences_of(this);
}

但我讨厌编写 WET 代码。还有其他方法吗?

【问题讨论】:

  • 所以,你想实现多态性(“我想要的是 func() 依赖于类类型”)但不想使用内置做多态的工具?
  • 为什么要让虚函数(动态多态)调用模板(静态多态)?你真的从模板分离中获得了什么吗?它对不同类型有什么不同吗?如果是,为什么不能直接将不同的东西放在虚函数实现中,而不是在模板中?您可能应该描述您正在尝试做的事情,而不是您目前正在尝试做的事情,因为这很可能是一个 x/y 问题。
  • @underscore_d 编辑了我的问题。
  • IMO 如果您必须使用typeid(),那么这通常表明您的设计可以重新考虑。不过,我没有立即提出替代建议。

标签: c++ templates inheritance types


【解决方案1】:

使用奇怪重复的模板模式 (CRTP):

template <typename Derived>
struct Base {
    void foo() {
        func(static_cast<Derived*>(this));
    }
};

struct A : Base<A> { };
struct B : Base<B> { };

int main() {
    A a;
    B b;
    a.foo();
    b.foo();
}

【讨论】:

  • 注意:当我写下这个答案时,这个问题看起来大不相同。
【解决方案2】:

您应该使用对象的动态类型的type_index 而不是类型模板参数的type_index 来访问映射。

consequences[typeid(*event)]

只要确保Event 至少有一个虚函数即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 2016-08-17
    • 2021-03-19
    • 2021-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多