C ++ / Java继承与委派等

时间:2009-04-07 20:52:02

标签: c++ inheritance delegation

我正在创建一个包含许多不同选项的类库,以便进行可能的自定义。例如,您可以设计您的类以便它可以执行FeatureX(),或者您可以设计您的类以便它可以执行FeatureY()。

在正常情况下,您只需使用名为FeatureX的纯虚方法创建接口IFeatureX,使用名为FeatureY的纯虚方法创建另一个接口IFeatureY。如果一个类同时具有FeatureX和FeatureY,它可以从两者继承,没问题。

我的问题是,如果函数/方法需要一个可以同时执行FeatureX()和FeatureY()的对象,该怎么办?我如何用C ++表达类型,但Java中的答案也有帮助,以确保FeatureX和FeatureY都可用?

我是否创建了继承自IFeatureX和IFeatureY的另一个接口IFeatureXY?好的...如果只有两个功能我可以逃脱这个。但如果说有10个特征,那么可能的接口数量会变得很大。

有一种简单的方法吗?我尝试使用C ++模板和委托来解决问题,但没有走得太远。我希望有一个简单的解决方案,可能有一个我忽略了。

我感谢你们的任何帮助和建议。

感谢。

7 个答案:

答案 0 :(得分:2)

要做的第一件事就是问你是否想要做一些不能简单表达的事情,如果是这样,问问自己这是否值得做?

鉴于您无法找到您想要的更简单的模型,您将需要考虑选项之间的依赖关系。如果您可以独立于功能Y使用功能X,则将它们设置为独立接口或纯虚拟类(根据语言而定)。

如果您不能独立使用它们,请创建一个包含两者的类;问问自己为什么要将FeatureX和FeatureY作为单独的接口,因为这种使用模式表明它们毕竟不是独立的。

答案 1 :(得分:2)

如果您不怕使用模板,可以将您的功能设为模板,并使用SFINAE检查两个接口:

template <class T>
void my_function(const T& data, typename enable_if_c<
    is_convertible<T*, IFeatureX*>::value && 
    is_convertible<T*, IFeatureY*>::value>::type*=0) {
  ...
}

这将为扩展两个特征接口的每个类型创建一个方法(请注意,它不需要SFINAE技巧;一个不受约束的模板可以工作,但是当你传递一个没有的类型时,它就无法编译符合要求)。

另一种可能性是创建一个扩展接口的IFeatureXY接口,并在函数参数中使用它;这样做的缺点是的类型实现了两个接口,但是这个联合接口不能用于这种方法。

此外,您可以向函数传递两个参数,每个接口一个,并要求它们是指向同一对象的指针;这是脆弱的,但可以通过制作一些模板类来保持两个指针来加强 - 例如。 product_type<IFeatureX*, IFeatureY*>,它将由有问题的单个对象初始化,并保留两种类型。

在Java中,你可以用有界类型变量做同样的事情(如果它们允许多个边界;我现在不确定)。

答案 2 :(得分:1)

虽然有多种方法可以添加完全不同的功能,但您可能需要考虑这些添加功能的范围。它们会与您的主类库相关吗? (有人可能会争辩说,如果他们不是,他们就不应该参与其中)

如果他们有足够的共同点来保证添加功能,你可以寻找类似装饰器模式(http://en.wikipedia.org/wiki/Decorator_pattern)的东西。它可以让你通过这样的事情绕过一些不稳定的问题。

答案 3 :(得分:0)

如果你想在c ++中完成它,那么多重继承呢?

答案 4 :(得分:0)

可能你太精细了。考虑一个数字类 - 您可以执行乘法,除法,加法,减法等。但是,您不会为这些操作中的每一个创建单独的接口 - 您将创建一个名为SupportsArithmetic(或其他)的接口来覆盖它们。

答案 5 :(得分:0)

WCF具有非常好的模式,如何使用IExtensionCollection<T>.Find<E>()确定某个对象是否支持某个接口(或类)。 IExtensionCollection

IFeatureX feature = argument.Find<IFeatureX>();

if (feature != null)
{
    // Find() returned an instance so there is an implementation
    // of IFeatureX available

   feature.FeatureX();
}

这样您就可以查询对象的某些界面。在IUnknown::QueryInterface()中的COM +中使用了类似的方法。

答案 6 :(得分:0)

为什么需要接口?使用模板:

template< typename T >
void some_function( const T& t )
{
    // use featureX functions
    t.fetatureX();

    // use featureY functions
    t.featureY();
}

用法:

SomeClass x; // object with only X feature
some_function( x ); // compile time error, because featureY() doesn't exists