2013-03-08 2 views
1

У меня есть три класса, и я хочу, чтобы использовать каждый из них в другой likeso:Круговое Наследование в C++

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

Таким образом, проблема здесь в том, что я получаю ошибку на компиляции, который говорит базовые неопределенные, I попытались использовать #define и #ifdefine, но это не работает.

В идеале, что я хочу сделать, это есть один объект в main для вызова и все другие переменные, которые будут использоваться, будет там и в то же время этот объект может быть другим таким образом, что это может быть Line или Circle ,

+3

Ключевое слово 'public', а не' Public' –

+0

Итак, что это значит? – Alyafey

+0

Я не уверен, что то, что вы просите, имеет смысл: не могли бы вы переформулировать вопрос? – 2013-03-08 00:31:32

ответ

2

Я предполагаю, что вы хотите, чтобы любой объект был либо примитивным графическим объектом, как линия или круг, либо составным объектом, т.е. объект, содержащий несколько других.

Ваши фактически почти нет: то, что вы должны сделать, это:

  • удалить Object подклассы экземпляров из Object (см других ответов по той причине, за это время дизайна ошибка),

  • создать четвертый класс наследование Object:

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

Теперь, если вы хотите манипулировать в общем виде списком объектов, это легко. Все, что вам нужно, это определить специальные виртуальные методы на Object и переопределить их в подклассах (например, метод draw).

См. this tutorial о полиморфизме для более подробного объяснения концепции.

+0

Да, вы правы, я сделал это, создав другой класс, содержащий мои объекты – Alyafey

3

вы не можете сделать это. Компилятор не может это сделать.

Вместо этого у вас должны быть указатели на объекты, а не прямые экземпляры их.

Тогда делает так называемое «вперед» заявление классов:

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

Конечно, было бы лучше использовать смарт-указатели, а не сырые.

+0

OK спасибо .... – Alyafey

0

Для того чтобы переменная-член имела данный тип (например, 'Circle c'), определение класса должно было уже появиться в модуле перевода. Итак, в этом случае то, что вы просите, невозможно.

Однако указатель на объект требует, чтобы компилятор знал, что символ (например, «Круг») представляет класс. Вы можете сделать это с помощью forward class declaration. Поэтому вариант является

class Circle; 
class Line; 

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

class Line: public Object { ... } 

class Circle: public Object { ... } 
0

В коде Object объект содержит (элемент данных) в Circle подобъектов, который, в свою очередь, содержит Object подобъектов (базовый класс суб-объект), который & hellip;

Это дает бесконечный размер, что довольно неточно.

Однако решение очень просто: не выведите эти классы из Object.

1

Вдумайтесь:

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

Вы НЕ можете делать то, что вы только что описали. Базовый класс не должен содержать классы, которые вытекают из него. Когда класс выводится, он содержит все компоненты базового класса. Поэтому в вашем примере объект содержит строку и круг. Круг содержит объект, который содержит Circle и Line - вы можете видеть, что мы можем это сделать так же, как число 3 в 1/3 ...

Вы можете либо иметь ссылку, либо указатель на объект класса Line или Circel, например

class Line; 
class Circle 

Вы должны эти строки перед классом Object - это говорит компилятор

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


protected: 

    int x; 
    int y; 
private: 
    Line* l; 
    Circle* c; 
}; 
«Там есть класс Line и класс Circle Приеду к тому, что они на самом деле содержат позже ....»
Смежные вопросы