2013-09-22 64 views
0

我的问题是:“我如何实现处理不同子类但能访问来自两个基类的方法的泛型函数?从另一个基类的多个继承和通用访问一个基类

我请你想象,我使用的结构如下假设的图形库:

class Shape 
{ 

// getters and setters are here 

private: 
    int m_BorderColor; 
    int m_FillColor; 
} 

class Square : public Shape 
{ 

} 

class Triangle : public Shape 
{ 

} 

class TextBox : public Shape 
{ 

} 

...等等。

该库只允许将Shape基类的衍生物添加到其假设画布中。在我的应用程序中,我希望在每个形状和可能的其他属性中都有一个文本框。

因此,我想有自己的基类,类似如下:

class MyBase 
{ 
public: 
    SetText (string text) { m_Text.Text = text; } 
    // other getters and setters here 

private: 
    TextBox m_Text; 
    int m_Id; 
} 

然后我就可以有“我”的形状与文本框,如下所示:

class MySquare : public Square, public MyBase 
{ 

} 

我可以将MySquare添加到画布,因为它是Shape的子类。当用户双击MySquare(或MyTriangle等)时,我想更改文本。但我只知道在运行时点击哪个形状。

以下显然行不通,因为的setText不是外形与我从库中接收所述指针的构件,尽管(例如)是一种MyTriangle,被转换为外形:

// double click handler 
Shape* clicked_shape = clickEvent.GetShape(); 
clicked_shape->SetText("Foo"); 

我需要使用基类指针,因为我不知道直到运行时才得到哪个形状对象。因此,虽然以下工作正常,但对我无用:

// double click handler 
Shape* clicked_shape = clickEvent.GetShape() 
((MyTriangle*)clicked_shape)->SetText("Foo") 

谢谢您对此问题的任何见解或更好的模式!

回答

1

这是怎么回事?

MyBase * base = dynamic_cast<MyBase *>(clicked_shape); 
base->SetText("too"); 

您可能要检查base被空,如果你得到的形状实际上不是你的一个。

MyBase至少需要一个虚拟函数 - 析构函数会这样做。

+0

dynamic_cast是最后的手段。在很多情况下,这表明设计不好。但有些时候这是不容易避免的。 – dmitri

+0

@dmitri我同意;我不经常使用它。但这正是它设计的问题类型。 –

+0

我尝试了这样的东西,但与static_cast。问题是,取决于哪个形状是MyBase部分的偏移量不同,所以SetText访问器崩溃。对不起,但dynamic_cast解决了这个问题吗? – iwbnwif

0

Shape类是一个基类,因此它提供了一个可以被覆盖的接口。例如。可能有draw()方法被称为绘制形状。这将是一个很好的候选人,在您的新课程中用文本框覆盖。例如:

class SquareWithText: public Square { 
    void draw() { 
    Square::draw(); // call base method 
    ... // add text box here 
} 

这里没有多重继承,这为您提供了一个更简单的解决方案。 如果单一继承不适合你,你可能会寻求更复杂的解决方案。

class ShapeWithTextBox : public Shape { 
    void draw() { 
    ... // add text box here 
    } 
} 

现在你会写你的新类为:

class MySquare : public Square, public ShapeWithTextBox 
{ 
    void draw() { 
    Square::draw(); 
    ShapeWithTextBox::draw(); 
} 

这是没有必要从Shape获得ShapeWithTextBox。它取决于Shape class的接口。

+0

谢谢,这是一个有趣的答案,但是当我从doubleclick事件中得到一个指针时,它将是一个Shape *。我如何使用它来访问ShapeWithTextBox的成员?我不能施放它,因为根据它的形状,第二个基类的地址将被不同的数量抵消。 – iwbnwif

+0

另外我只注意到你的MySquare类可能遭受'钻石'多重继承问题,因为Shape是Square和ShapeWithTextBox的超类 – iwbnwif

+0

钻石问题 - 欢迎来到多继承解决方案:) – dmitri