【问题标题】:Circular Inheritance in c++c++中的循环继承
【发布时间】:2013-03-08 00:26:02
【问题描述】:

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

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, 我试过用#define#ifdefine,但是不行。

理想情况下,我想做的是在main 中有一个对象进行调用,所有其他要使用的变量都将设置在那里,同时该对象可能不同,因此它可能是@987654325 @ 或 Circle

【问题讨论】:

  • 关键字是public,不是Public
  • 那是什么意思?
  • 我不确定您的问题是否合理:您能否重述问题?
  • 是的,我认为您需要重新表述您的问题,因为这没有多大意义。

标签: c++ inheritance virtual


【解决方案1】:

你不能这样做。编译器是不可能做到的。

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

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

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

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

【讨论】:

    【解决方案2】:

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

    你实际上已经快到了:你应该做的是:

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

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

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

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

    有关多态性的更多解释,请参阅this tutorial

    【讨论】:

    • 是的,你是对的,我现在通过创建包含我的对象的其他类来做到这一点
    【解决方案3】:

    想一想:

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

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

    相反,使用forward declarations 和(智能)指针(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();
    };
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        为了使成员变量属于给定类型(如“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 { ... }
        

        【讨论】:

          【解决方案6】:

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

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-05-18
            • 1970-01-01
            • 1970-01-01
            • 2022-01-16
            • 2021-08-25
            • 1970-01-01
            • 2018-05-07
            相关资源
            最近更新 更多