组成你继承的类的对象?

时间:2010-02-03 23:06:30

标签: c++ inheritance composition

我有一个类Parameter,其目的是表示某个参数可以容纳的可能值(实现两个关键方法,GetNumValues()和GetValue(int index))。

通常一个逻辑参数(参数值是位标志)最好由2个或更多参数类实例表示(即参数可以是1或2,参数可以是4或8,而不是1参数可以是5,6,9或10)。为了解决这个问题,我想创建一个包含Parameters的CompositeParameter类,并根据它所拥有的参数组合实现GetNumValues()和GetValue()函数。

由于CompositeParameter正在组合参数以使它们充当单个参数,因此“CompositeParameter是一个参数”关系是有意义的。所以我发现自己处于这样一种情况,即我有一个类,它组成了一个继承自的类的对象,这似乎不对。但与此同时,我不明白为什么更高级别的代码不能完全相同地处理CompositeParameters和Parameters。

我能想到的唯一选择是让CompositeParameter简单地组合参数,而更高级别的代码只处理CompositeParameters。然而,这有点浪费b / c一般情况下是CompositeParameters只包含一个参数。

思想?

class Parameter
{
public:
    virtual unsigned int GetNumValues() const {...}
    virtual unsigned int GetValue(unsigned int index) const {...}
}

class CompositeParameter : public Parameter
{
public:
    // product of GetNumValues() of each item in mParamList
    virtual unsigned int GetNumValues() const {...} 

    // allow all the possible combinations of the items in mParamList to be
    // treated as one parameter. i.e. if mNumParams = 2, this would be analogous
    // to getting the row and col index of a matrix from index, and combining
    // the mParamList[0]->GetValue(row) and mParamList[1]->GetValue(col)
    virtual unsigned int GetValue(unsigned int index) const {...}

private:

    static const unsigned int MAX_PARAMS = 10;

    unsigned int mNumParams;
    const Parameter* mParamList[MAX_PARAMS];
}

2 个答案:

答案 0 :(得分:2)

这似乎是一个非常合理的设计。我要做的唯一改变是将参数从类更改为接口。

然后你可以有一个实现Parameter的Parameter类(或者一个ParameterImpl类),还有一个也实现Parameter接口的CompositeParameter类

答案 1 :(得分:1)

I have a class which composes objects of a class it inherits from,
which just doesn't seem right.

这不是复合材料的定义吗?

(parameter values are bit flags)

这是我要质疑的设计部分。也许Flag的一个更好的名字是FlagSet?

隐藏接口背后的按位测试是可以的,但似乎继承可能会解决基本计算机科学中众所周知的解决方案的问题。


However, that is somewhat wasteful b/c the general case would be
CompositeParameters which contained just one Parameter.

复合模式的要点是Leaf对象表示简单情况,Composite对象表示复杂情况,客户端代码可以处理两种情况相同。如果您的接口需要客户端代码来区分这两者,或者遍历基类组件,那么您实际上并没有从使用该模式中获得任何价值。

例如,如果您的主要关注点是测试,那么基类可以有一个方法:

bool Test() const;

叶类实现如下:

bool LeafTester::Test() { return _DoTest(); }

复合类实现如下所示:

bool CompositeTester::Test() {
    bool success = true;

    for (int i = 0; i < m_count; i++)
        success &= m_components[i].Test();

    return success;
}

客户总是会使用这样的代码:

// tester could be a Composite or a leaf, but we don't care:
bool testResult = tester.Test();

我使用for循环来保持示例简单。在实践中,我会改用STL。