我想将基类指针转换为派生类指针作为函数参数,而不使用dynamic_pointer_cast
class Base
{
public:
typedef std::shared_ptr < Base > Ptr;
virtual ~Base ( );
...
};
class Derive : public Base
{
public:
typedef std::shared_ptr < Derive > Ptr;
...
};
void foo( Derive::Ptr ptr )
{
...
}
Base::Ptr ptr1 ( new Derive );
foo( ptr1 );
上面的代码在调用foo时会出错。通过使用std :: dynamic_pointer_cast将ptr1类型转换为Dervie指针可以避免这种情况。
Base::Ptr ptr1 ( new Derive );
foo ( std::dynamic_pointer_cast < Derive > ( ptr1 ) );
我想创建一个回调函数映射,它将自动对基类指针进行类型转换,并根据派生类的类型调用相应的函数。
答案 0 :(得分:2)
这适合我。
#include <iostream>
#include <set>
#include <memory>
class Base
{
public:
typedef std::shared_ptr < Base > Ptr;
virtual ~Base () {}
};
// Dispatch mechanism to dispatch derived class specific
// functions for foo.
// Base class.
struct FooDispatcher
{
static int registerDispatcher(FooDispatcher* dispatcher)
{
dispatcherSet.insert(dispatcher);;
return 0;
}
static void dispatch(Base::Ptr ptr)
{
std::set<FooDispatcher*>::iterator iter = dispatcherSet.begin();
std::set<FooDispatcher*>::iterator end = dispatcherSet.end();
for ( ; iter != end; ++ iter )
{
if ( (*iter)->canProcess(ptr) )
{
(*iter)->process(ptr);
return;
}
}
}
virtual bool canProcess(Base::Ptr ptr) = 0;
virtual void process(Base::Ptr ptr) = 0;
static std::set<FooDispatcher*> dispatcherSet;
};
std::set<FooDispatcher*> FooDispatcher::dispatcherSet;
void foo( Base::Ptr ptr )
{
FooDispatcher::dispatch(ptr);
}
// A class template for derived classes to use when they
// have an implementation of foo.
template <typename T>
struct FooDerivedDispatcher : public FooDispatcher
{
virtual bool canProcess(Base::Ptr ptr)
{
return (std::dynamic_pointer_cast<T>(ptr) != nullptr);
}
virtual void process(Base::Ptr ptr)
{
fooImpl(std::dynamic_pointer_cast<T>(ptr));
}
};
// Derived1 and its implementation of foo.
class Derived1 : public Base
{
public:
typedef std::shared_ptr < Derived1 > Ptr;
};
void fooImpl( Derived1::Ptr ptr )
{
std::cout << "Came to fooImpl(Derived1::Ptr).\n";
}
// Register the FooDispatcher for Derived1
int dummy1 = FooDispatcher::registerDispatcher(new FooDerivedDispatcher<Derived1>());
// Derived2 and its implementation of foo.
class Derived2 : public Base
{
public:
typedef std::shared_ptr < Derived2 > Ptr;
};
void fooImpl( Derived2::Ptr ptr )
{
std::cout << "Came to fooImpl(Derived2::Ptr).\n";
}
// Register the FooDispatcher for Derived1
int dummy2 = FooDispatcher::registerDispatcher(new FooDerivedDispatcher<Derived2>());
// Test...
int main()
{
Base::Ptr ptr(new Derived1);
foo(ptr);
ptr = Base::Ptr(new Derived2);
foo(ptr);
}
输出:
Came to fooImpl(Derived1::Ptr). Came to fooImpl(Derived2::Ptr).
<强>更新强>
更简单的调度机制......感谢@MooingDuck。
#include <iostream>
#include <vector>
#include <memory>
class Base
{
public:
typedef std::shared_ptr < Base > Ptr;
virtual ~Base () {}
};
struct FooDispatcher {
template<class Derived, class Func>
bool registerFunction(Func func) {
auto lambda = [=](std::shared_ptr<Base>& ptr)->void {
std::shared_ptr<Derived> d = std::dynamic_pointer_cast<Derived>(ptr);
if (d)
func(std::move(d));
};
functions.push_back(lambda);
return true;
}
void dispatch(std::shared_ptr<Base>& ptr)
{
for(auto& func : functions)
func(ptr);
}
private:
std::vector<std::function<void(std::shared_ptr<Base>&)>> functions;
};
FooDispatcher dispatcher;
void foo( Base::Ptr ptr )
{
dispatcher.dispatch(ptr);
}
class Derived1 : public Base
{
public:
typedef std::shared_ptr < Derived1 > Ptr;
};
void fooImpl1( Derived1::Ptr ptr )
{
std::cout << "Came to fooImpl(Derived1::Ptr).\n";
}
class Derived2 : public Base
{
public:
typedef std::shared_ptr < Derived2 > Ptr;
};
void fooImpl2( Derived2::Ptr ptr )
{
std::cout << "Came to fooImpl(Derived2::Ptr).\n";
}
int main()
{
dispatcher.registerFunction<Derived1>(fooImpl1);
dispatcher.registerFunction<Derived2>(fooImpl2);
Base::Ptr ptr(new Derived1);
foo(ptr);
ptr = Base::Ptr(new Derived2);
foo(ptr);
}