2

我有三个类,我想在另一个类中使用它们中的每一个:

class Object
{
public:
    Object();
    ~Object();


protected:

   int x;
   int y;
private:
  Line l;
  Circle c;
}; 

class Line : public Object
{
public:
    Line ()
        {
           x = x+y;
         }
    ~Line ();


private:
}; 

class Circle : public Object
{
public:
    Circle()
        {
           x = x/y;
         }
    ~Circle();


private:
}; 

所以这里的问题是我在编译时收到一个错误,上面写着 base undefined,我尝试使用#defineand #ifdefine,但它不起作用。

理想情况下,我想做的是让一个对象main调用,所有其他要使用的变量都将设置在那里,同时这个对象可能不同,因此它可能是 aLineCircle

4

6 回答 6

4

你不可以做这个。编译器不可能做到这一点。

相反,您必须拥有指向对象的指针,而不是它们的直接实例。

然后对类进行所谓的“前向”声明:

class Circle;
class Line;
class Object
{
    Line* line;
    Circle* circle;
}

当然,最好使用智能指针而不是原始指针。

于 2013-03-08T00:37:19.507 回答
3

考虑一下:

  1. 每个Object包含一个Line;
  2. 每个Line都是一个Object
  3. 因此,每个都Object包含一个Object;
  4. 当然,Object它又包含一个Object;
  5. 其中包含一个Object... 等等,直到你累了。

这是建立无限递归数据结构的尝试,您可能会明白为什么不允许这样做。

相反,使用前向声明和(智能)指针(unique_ptr<>似乎是这里的最佳选择)来打破相互依赖并允许终止递归结构(指针可以为空):

#include <memory>

// Forward declarations
class Line;    
class Circle;

class Object
{
public:
    Object();
    ~Object();
protected:
   int x;
   int y;
private:
  std::unique_ptr<Line> l;
  std::unique_ptr<Circle> c;
};

class Line : public Object
{
public:
    Line ()
        {
           x = x+y;
         }
    ~Line ();
};

class Circle : public Object
{
public:
    Circle()
        {
           x = x/y;
         }
    ~Circle();
};
于 2013-03-08T00:40:38.130 回答
3

我的猜测是,您希望任何对象都是原始图形对象,例如线或圆,或者是复合对象,即。包含其他几个对象的对象。

您实际上几乎就在那里:您应该做的是:

  • 从 Object中删除Object子类实例(请参阅其他答案,因为这是一个设计错误),

  • 创建第四个类继承Object

    class Compound : public Object {
      public:
        Compound(){
        }
      private:
       Line line;
       Circle circle;
    };
    

现在,如果您想以通用方式操作对象列表,这很容易。您只需要在 上定义临时虚拟方法Object,并在子类中覆盖它们(例如draw方法)。

有关该概念的更多解释,请参阅本教程关于多态性。

于 2013-03-08T01:06:25.567 回答
1

你不能做你刚才描述的事情。基类不得包含派生自它的类。当一个类派生时,它包含基类的所有组件。因此,在您的示例中,对象包含一条线和一个圆。圆包含包含圆和线的对象 - 你可以看到我们可以像 1/3 中的 3 的数量一样...

您可以拥有指向 Line 或 Circel 类对象的引用或指针,例如

class Line;
class Circle

您需要在 Object 类之前使用上述行 - 它告诉编译器“有一个类 Line 和一个类 Circle。我稍后会谈到它们实际包含的内容......”

class Object
{
public:
    Object();
    ~Object();


protected:

   int x;
   int y;
private:
  Line* l;
  Circle* c;
}; 
于 2013-03-08T00:41:24.897 回答
0

为了使成员变量具有给定类型(如“ Circle c”),类定义必须已经出现在翻译单元中。所以,在这种情况下,你问的是不可能的。

然而,一个指向对象的指针只需要编译器知道一个符号(例如'Circle')代表一个类。您可以通过前向类声明来做到这一点。所以一个选项是

class Circle;
class Line;

class Object {
public:
    ...
    Circle *c;
    Line *l;
}

class Line: public Object { ... }

class Circle: public Object { ... }
于 2013-03-08T00:38:56.950 回答
0

在您的代码中,一个Object对象包含一个Circle子对象(数据成员),该子对象又包含一个Object子对象(基类子对象),它......

这会产生无限大小,这是相当不好的。

但是,解决方案非常简单:不要从Object.

于 2013-03-08T00:40:10.340 回答