【问题标题】:Creating classes to represent different permutations of a type创建类来表示一个类型的不同排列
【发布时间】:2014-02-17 11:56:44
【问题描述】:

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

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 类中的几条数据......我真的不想传递所有这些信息。模式类将变得同样无用并且根本不灵活。我只是想不出一个干净的方法来处理这个问题。我能想到的最好的办法是让模式类做它可以做的事情,而不必向它传递各种废话,但现在界面只是愚蠢和尴尬。有什么想法吗?

【问题讨论】:

  • 我很困惑。你所描述的只是尖叫“使用继承”。如果不了解模式的实际实现,恐怕很难提供帮助。

标签: c++ class


【解决方案1】:

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

如果您使用基类并继承它,则只需将不希望派生类拥有的东西给它们private 访问修饰符,然后将protectedpublic 用于其他(当然视情况而定)。这样,您的派生类只获取他们需要的信息。您还可以有一个需要在每个较低类中设置的实例变量,以定义有关每个派生类的内容。访问修饰符是你的朋友。

如果您使用接口,只需包含每个图表所需的所有内容,然后在构建各个类时,只需从那里自定义它们以包含特殊内容。

如果由我个人决定,我会通过接口继承,但这只是我自己。

【讨论】:

    【解决方案2】:

    我之前遇到过这种问题(现在仍然不时......)

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

    执行此类操作的一种方法是创建根据当前类型和模式调用的函数。假设你必须画线,模式可以设置为 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;
    
        ...
        }
    }
    

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

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

    通过这种方式,您可以创建一个间接并使其在现有的具有大型 switch 或许多 if() 语句的大型函数中更加简洁,而不会将现有的“强大”类分解为许多可能变得难以使用的部分(因为如果它那么大,它可能已经在使用...)

    【讨论】:

      猜你喜欢
      • 2020-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 2017-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多