如何避免特定类方法的C ++强制转换?设计模式?

时间:2011-03-25 12:15:05

标签: c++ inheritance casting design-patterns

假设我有这样的事情:

class Father {
    public:
      virtual int genericMethod (void) =0;
  };

class Son1: public Father {
  public:
    int genericMethod ()
      { }
  };

class Son2: public Father {
  public:
    int genericMethod ()
      { }
    int specifClassMethod()
      { }
  };

在主要内容中,我执行以下操作:

Father * test = new Son2();

test->specifClassMethod(); //Can't do this! It is specific of Class Son2 and is not a virtual method in class Father!

这里的主要问题是了解通过父接口访问Son2特定方法的更好方法。我想知道是否有设计模式来解决这个问题或其他方式。我不想做演员表,我也不想在我的代码中加入很多'if'。

此致

爱德华

7 个答案:

答案 0 :(得分:2)

也许访客模式是您正在寻找的模式。

How Visitor Pattern avoid downcasting

答案 1 :(得分:2)

可能的方法是使用可选方法的特定接口,以及在基类中获取此接口的虚拟方法(可能返回零):

class SpecificInterface {
public:
  virtual ~SpecificInterface()
  { }
  virtual int specifClassCmethod() = 0;
  { }
};

class Father {
  public:
    virtual int genericMethod (void) = 0;
    virtual SpecificInterface* getSpecificInterface (void) =0;
};

class Son1: public Father {
  public:
    int genericMethod ()
      { }
    SpecificInterface* getSpecificInterface (void)
      { return 0; }
  };

class Son2: public Father, public SpecificInterface {
  public:
    int genericMethod ()
      { }
    int specifClassCmethod()
      { }
    SpecificInterface* getSpecificInterface (void)
      { return this; }
  };

用法如下:

Father * test = new Son1();
SpecificInterface * specificAPI = test->getSpecificInterface();
if( specificAPI )
  specificAPI->specifClassCmethod();

答案 2 :(得分:1)

你也无法通过演员合法解决这个问题,因为“test”指的是一个Father对象,而不是一个Son2对象。转换对象类型意味着“相信我,编译器,这个变量实际上包含X”。它不会以某种方式神奇地将基础对象转换为派生对象;它只告诉编译器你已经知道它没有的东西。

如果您希望行为与派生类不同,则将行为移动到虚拟方法中 - 即,想要调用specificCLassMethod()的代码属于父虚拟方法。

答案 3 :(得分:0)

没有。要调用仅存在于子类中的方法,您必须转换为ch ild类。

虽然您可以创建一个将函数名称映射到函数的映射,但是可以从子类的构造函数向它添加函数,然后使用test->callMethod("name");之类的函数来使所有这些函数具有相同的签名或使用varargs传递不太好的参数。

答案 4 :(得分:0)

您可以static_cast<Son2*>(test)->specifClassCmethod();,但仅在Father * test = new Son2();

时才有效

答案 5 :(得分:0)

如果您确实拥有Son2特有的内容,那么dynamic_cast<>就是您应该使用的内容。如果它可以作为虚函数添加到具有默认空行为的基类,那么您可以在没有强制转换的情况下解决您的问题(但这不是您在问题中所述的那样做)

解决您问题的一种设计模式是使用proxy object。该对象可以调用所有方法,并将它们委托给真实对象。

代理模式的优点:

  • 集中了将背后的对象区分为一个地方所需的逻辑
  • 您可以轻松添加一些日志
  • 客户端代码仍然很简单,Son类可以从额外的东西中清除

答案 6 :(得分:0)

首先,你不能为“父”类创建一个实例,因为它是一个抽象类(它有一个虚拟的int genericMethod(void)= 0; -pure虚函数)。而不是一个实例可以分配给它....

Son1* obj_son = new Son1();
Father* obj = obj_son;
//now if you call generic method - son1 method will be called(Father method is over ridden)
obj->genericMethod();
//similarly for son2 class
Son2* obj_son2 = new Son2();
Father* obj2 = obj_son2;
obj2->genericMethod();
obj2->specifClassCmethod();