场景:我有以下定义的类. class Baseclass { };class DerivedTypeA : public Baseclass { };class DerivedTypeB : public Baseclass { };// ... and so on ...class Container{ listBaseclass* stuff; listDerivedTypeA* specific_stuff;// ... in
class Baseclass { }; class DerivedTypeA : public Baseclass { }; class DerivedTypeB : public Baseclass { }; // ... and so on ... class Container { list<Baseclass*> stuff; list<DerivedTypeA*> specific_stuff; // ... initializing constructors and so on ... public: void add(Baseclass * b) { stuff.add(b); } void add(DerivedTypeA * a) { stuff.add(a); specific_stuff.add(a); } }; class ContainerOperator { Container c; // ... initializing constructors and so on ... public: void operateOnStuff(Baseclass * b) { // This will always use "void add(Baseclass * b)" no matter what object b really is. c.add(b); } }; // ... containerOperator.operateOnStuff(new DerivedTypeA());
所以,我想要做的是在Container中以某种特殊方式处理某个派生类.
问题:从不调用void add(DerivedTypeA * a).我显然做错了什么.做我想做的事情的正确方法是什么?
C中的重载分辨率发生在编译时,而不是运行时.解决这类问题的“通常”方法是使用 Visitor pattern.您可以通过使用CRTP实现Visitor来减少样板复制粘贴的数量.
如果使用CRTP for Base :: accept,则无需在派生类中再定义它.
这是一个与你类似的程序,但有点简单:
#include <iostream> class Base; class Derived; struct Operation { void add(Base *b) { std::cout << "Base\n"; } void add(Derived *b) { std::cout << "Derived\n"; } void visit(Base *b); // need to define this after Base class }; struct Base { virtual ~Base() {} virtual void accept(Operation &o) { o.add(this); } }; void Operation::visit(Base *b) { b->accept(*this); } struct Derived : public Base { void accept(Operation &o) { o.add(this); } }; int main() { Operation o; Base b; Derived d; Base *ptrb = &b; Base *ptrd = &d; o.add(ptrb); // These two print "Base" o.add(ptrd); o.visit(ptrb); // "Base" o.visit(ptrd); // "Derived" }