创建类来表示类型的不同排列

时间:2014-02-16 22:55:09

标签: c++ class

假设我有一个类结构(简化我的实际类):

class Graph
{
};

class DerivedGraph : public Graph
{
};

class DerivedGraph2 : public Graph
{
};

我想扩展此结构以考虑同一图表的不同变体。理想情况下,我希望能够做到这样的事情:

class Graph
{
};

// Removed
//class DerivedGraph : public Graph
//{
//};

// Removed
//class DerivedGraph2 : public Graph
//{
//};

class DerivedGraph3 : public Graph // really just a mode of DerivedGraph
{
};

class DerivedGraph4 : public Graph // really just a second mode of DerivedGraph
{
};


class DerivedGraph5 : public Graph // really just a mode of DerivedGraph2
{
};

class DerivedGraph6 : public Graph // really just a second mode of DerivedGraph2
{
};

但是你可以在这里快速看到问题 - 我必须在这里创建太多的类。此外,基类非常复杂和庞大(底线是它很简单)...所以我不想做太多结构上的改变。我希望在图形本身的层面上灵活地定义事物,但同时具有为一种图形类型的特定模式定义事物的灵活性。我希望能够使用诸如DoesGraphSupportNormalizedData()之类的虚函数或类似的东西(这只是一个简单的例子)。然后每个类都会覆盖此方法。

我的另一个想法是为模式本身创建一个单独的类结构(Graph类将创建它的实例),如:

class BaseMode
{
};

class Mode1 : public BaseMode
{
};

class Mode2 : public BaseMode
{
};

现在的问题是这些模式类需要访问Graph类中的几个数据......我真的不想传递所有这些信息。模式类将变得无用,根本不灵活。我只是想不出一个干净的方式来处理这个问题。我能想到的最好的方法是让模式类尽其所能,而不必将所有类型的垃圾传递给它,但现在界面只是愚蠢和笨拙。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

您可以使用用户和界面,也可以使用我从描述中收集的继承类。

如果您使用基类并继承它,只需要让您不希望派生类的内容只是为它们提供private访问修饰符,然后protected或{{1其他人(视情况而定)。这样,派生类只会获取所需的信息。您还可以拥有一个需要在每个较低类中设置的实例变量,以定义每个派生类的内容。访问修饰符是你的朋友。

如果您使用界面,只需包含每个图形所需的所有内容,然后在构建单个类时,只需从中定制它们以包含特色。

如果这取决于我,就个人而言,我会继续通过界面,但那只是我。

答案 1 :(得分:0)

之前我遇到过这种问题(现在还是......)

在这种情况下,你可能会采取错误的方式,你正在研究的是设备是一种专门的功能,具体取决于图形和模式的类型。继承很好,但它有其限制,如你所提到的。特别是因为用户可能想要切换图形的类型,但保留现有的图形对象。在这种情况下,继承没有帮助。

执行此类操作的一种方法是创建根据当前类型和模式调用的函数。假设您必须绘制线条,并且模式可以设置为LINE或DOTS。您可以使用两个绘制线条的函数,这些函数特定于模式或其他模式:

void Graph::draw_line_line(line l)
{
    // draw a line
}

void Graph::draw_line_dots(line l)
{
    // draw a dots along the line
}

现在,您可以定义一种表示该类型的渲染函数的类型及其变量成员:

typedef void (Graph::*draw_line_func)(line l);

draw_line_func    m_draw_line;

有了这个,您可以编写set_mode()函数,如下所示:

void Graph::set_mode(mode_t mode)
{
    m_mode = mode; // save for get_mode() to work
    switch(mode)
    {
    case LINE:
        m_draw_line = &Draw::draw_line_line;
        break;

    case DOTS:
        m_draw_line = &Draw::draw_line_dots;
        break;

    ...
    }
}

现在当你想渲染这条线时,你会调用这个专门的函数,你不需要知道它是LINE还是DOTS ......

void Graph::draw_line(line l)
{
    this->*m_draw_line(l);
}

通过这种方式,您可以创建一个间接,并在现有的具有大型开关或许多if()语句的大型函数中使其更加清晰,而不会破坏许多可能难以使用的现有“强大”类(因为如果它那么大它可能已经在使用......)