2011-03-25 59 views
1

假设我有这样的事情:如何避免C++为特定类方法强制转换?设计模式?

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'。

问候,

爱德华

+1

你的例子是有点做作,是否有可能使它更具体? – 2011-03-25 12:23:20

+0

为了比@Coda更加明确,您使用的实际设计是什么,以便我们能够指出它的缺陷?如果你的设计没问题,那么'dynamic_cast'是你的朋友。通常,使用'dynamic_cast'是嗅到代码的标志。 – 2011-03-25 12:27:04

+0

不要忘记添加虚拟析构函数到基类。否则,删除“Father * test = ...;删除测试;”不会调用正确的析构函数。 – 2011-03-25 12:36:21

回答

0

号调用哪只在子类中存在的方法,你必须强制转换为CH ILD类。

虽然您可以创建一个映射函数名称映射到函数,但从子类的构造函数中添加函数,然后使用类似test->callMethod("name");的东西,您必须使所有这些方法具有相同的签名或使用可变参数传递不太好的论据。

0

可以static_cast<Son2*>(test)->specifClassCmethod();但只有工作,如果Father * test = new Son2();

0

如果你真的有特定Son2的东西,然后dynamic_cast<>是你应该用什么。如果它可以作为一个虚拟函数添加到基类的默认空行为,那么你可以在没有演员的情况下解决你的问题(但这不是你想要做的,就像你在问题中说的那样)

解决您的问题的一种设计模式是使用proxy object。那个对象会让所有的方法容易被调用,并将它们委托给真实对象。代理模式的

优点:

  • 你集中精力区分后面一个地方的对象所需的逻辑
  • 你可以添加一些日志记录轻松地
  • 客户端代码保持简单,Son类从额外的东西中清理出来
1

因为“test”指向父对象而不是Son2对象。铸造对象类型意味着“相信我,编译器,这个变量实际上包含X”。它不会以某种方式神奇地将基础对象转换为派生对象;它只会告诉编译器你已经知道它没有的东西。

如果您希望行为因派生类而异,则将行为移至虚拟方法 - 即,想要调用specificCLassMethod()的代码属于Father的虚拟方法。

+0

这里有'dynamic_cast'。 – 2011-03-25 12:25:04

+0

不,那不是dynamic_cast所做的:它不能将一种类型转换为另一种类型。如果我有一个实际指向派生实例的指针,或者相反,dynamic_cast可以偏移指针以解释vtbls或其他隐藏的对象模型问题。这只有在对象的实际运行时类型如我所说的那样时才有效。 dynamic_cast不能神奇地将Son2的成员变量添加到父实例。 – 2011-03-25 12:31:56

0

首先,你不能为类“父亲”创建一个实例,因为它是一个抽象类(具有虚拟INT genericMethod(无效)= 0;制纯净虚拟函数)。相反,一个实例可以被分配给它....

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(); 
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(); 
相关问题