c ++中的循环继承

时间:2013-03-08 00:26:03

标签: c++ inheritance virtual

我有三个课程,我想在另一个课程中使用它们 likeso:

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:
}; 

所以这里的问题是我在编译时遇到错误,这个错误表示未定义, 我尝试使用#define#ifdefine,但它不起作用。

理想情况下,我想要做的是在main中调用一个对象,并在那里设置要使用的所有其他变量,同时这个对象可以是不同的,这样它就可以是LineCircle

6 个答案:

答案 0 :(得分:4)

你不能这样做。编译器不可能这样做。

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

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

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

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

答案 1 :(得分:3)

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

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

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

  • 创建继承Object的第四个类:

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

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

有关该概念的更多解释,请参阅有关多态的this tutorial

答案 2 :(得分:2)

想一想:

  1. 每个Object都包含Line;
  2. 每个Line都是Object;
  3. 因此,每个Object都包含Object;
  4. 当然,Object依次包含Object;
  5. 其中包含Object ......等等,直到你累了。
  6. 这是尝试设置无限递归数据结构,您可能会看到为什么不允许这样做。

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

    #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();
    };
    

答案 3 :(得分:1)

你不能做你刚刚描述的事情。基类不能包含从中派生的类。类派生时,它包含基类的所有组件。因此,在您的示例中,Object包含一个Line和一个Circle。圆形包含包含圆和直线的对象 - 您可以看到我们可以像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;
}; 

答案 4 :(得分:0)

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

但是,指向对象的指针只需要编译器知道符号(例如“Circle”)表示一个类。您可以通过forward class declaration执行此操作。所以选项是

class Circle;
class Line;

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

class Line: public Object { ... }

class Circle: public Object { ... }

答案 5 :(得分:0)

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

产生无限大小,这是非常好的。

但是,解决方案非常简单:不要从Object派生这些类。