c++ - 从基指针/引用调用正确的自由函数

标签 c++ design-patterns polymorphism virtual

让一个类层次结构:

class Base { virtual ~Base() throw(); };

class DerivedA : public Base { };

class DerivedB : public Base { };

我想要一些特定于每个派生类的代码。然而,该代码也特定于使用此类层次结构的应用程序,我不想将特定于派生类的代码嵌入到这些派生类中。为了避免这样做,我想到了编写免费函数:

void DerivedASpecificWork( DerivedA da );

void DerivedBSpecificWork( DerivedB db );

但是,当通过对 Base 的引用/指针给出派生类的实例时,我无权访问实例的实际类型,因此无法调用正确的 Derived*SpecificWork() 函数。

我想知道是否有某种设计模式允许我在不知道实例的实际类型的情况下调用特定于派生类的函数,即具有与虚函数提供的相同机制,但没有拥有这些虚拟函数需要我将特定于应用程序的代码嵌入到该类层次结构中。

实际上,我为什么要这样做是为了提供有关在由 Lua 脚本调用的 native 实现的函数中发生的异常的信息。每个异常都带有自己的一组信息,我想在脚本中表示错误的方式取决于异常的类型。我可以在基类中创建一个由派生类实现的纯虚方法,但这需要我将与 Lua 相关的代码嵌入到我的异常层次结构中,我不想这样做,因为 Lua 特定于其中一个使用该异常层次结构的应用程序。

我也不能使用 C++11。

谢谢。

最佳答案

也许 Brigde 模式可以帮助您。

当您想避免抽象与其实现之间的永久绑定(bind)时,可以使用此模式。

(我没有看到您对使用 c++11 的限制的评论,但您可以删除 std::unique_ptrstd::moveoverride 关键字)

class AppSpecificImp
{
public:
   virtual void DoWork() = 0;
};

class Base 
{ 
public:
   virtual ~Base() throw(); 

   virtual DoWork() = 0;
};

class DerivedA : public Base 
{ 
public:
   DerivedA(std::unique_ptr<AppSpecificImp> appImp)
      : imp(std::move(appImp))
   {
   }

   void DoWork() override
   {
       // DerivedA specific code 

       imp->DoWork();
   }

private:
   std::unique_ptr<AppSpecificImp> imp;
};

class DerivedB : public Base 
{ 
public:
   DerivedB(std::unique_ptr<AppSpecificImp> appImp)
      : imp(std::move(appImp))
   {
   }

   void DoWork() override
   {
       // DerivedB specific code 

       imp->DoWork();
   }

private:
   std::unique_ptr<AppSpecificImp> imp;
};

编辑以显示访问者模式的用法:

使用访问者模式,您可以做您想做的事,但需要付出更多的努力。

class Visitor
{
public:
   virtual void VisitDerivedA(DerivedA* object) = 0;

   virtual void VisitDerivedB(DerivedB* object) = 0;
};

class Base
{
public:
   virtual void Visit(Visitor* visitor) = 0;
};

class DerivedA : public Base 
{ 
public:
   virtual void Visit(Visitor* visitor)
   {
       visitor->VisitDerivedA(this);
   }
};

class DerivedB : public Base 
{ 
public:
   virtual void Visit(Visitor* visitor)
   {
       visitor->VisitDerivedB(this);
   }
};

class AppSpecificVisitor : public Visitor
{
public:
   void VisitDerivedA(DerivedA* object)
   {
       // Do any work related to DerivedA class
   }

   void VisitDerivedB(DerivedB* object)
   {
       // Do any work related to DerivedB class
   }
}


int main()
{
    AppSpecificVisitor myVisitor;

    Base* myBase = // any class in your hierarchy

    myBase->Visit(&myVisitor);
}

正如我在访问者模式的评论中所说,您可以在不更改主层次结构(基础->派生类型)的情况下添加新功能。您只需定义一个新的访问者实现并为主层次结构中的每个类编写逻辑。在您的示例中,您可以将特定于应用程序的逻辑打包到一个对象中,并在您的派生对象中引用该逻辑,这是一种更简单的方法。

关于c++ - 从基指针/引用调用正确的自由函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40802382/

相关文章:

c++ - 以下哪一种函数类型不能被重载?

c++ - 清除 vector<pointer> 然后重新使用它

java - java中如何扩展抽象类

python - 扩展 python - swig,而不是 swig 或 Cython

java - 为什么我们在Builder设计模式中需要 'Builder class'?

c++ - 设置 GL_TEXTURE_MAX_ANISOTROPY_EXT 会导致下一帧崩溃

design-patterns - 是否有一种设计模式可以在各种状态下表达对象(及其操作)?

c++ - 访问聚合器类中类之间共享的变量

c++将结构保存到文件中

c++ - 添加析构函数后,在程序调用它之前出现错误