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 不是 Shape 的成员,并且我从库中收到的指针(例如)被转换为 MyTriangle,但被转换为 Shape:

// 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")

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

4

2 回答 2

1

那这个呢?

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

base如果您获得的 Shape 实际上不是您的一个,您可能想要检查是否为空。

MyBase为此至少需要一个虚函数——析构函数就可以了。

于 2013-09-22T10:05:05.180 回答
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();
}

没有必要派生ShapeWithTextBoxShape。这取决于Shape class.

于 2013-09-22T09:47:36.620 回答