2

I have three classes and I want to use each of them inside another 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:
}; 

So the problem here is that I get an error on compilation which says base undefined, I have tried to use #define and #ifdefine, but it doesn't work.

Ideally, what I want to do is to have one object in main to call and all other variables to be used will be set there and at the same time this object could be different such that it could be a Line or Circle.

didierc
  • 14,572
  • 3
  • 32
  • 52
Alyafey
  • 1,455
  • 3
  • 15
  • 23

6 Answers6

4

you cannot do this. It's impossible for the compiler to do it.

Instead you must have pointers to the objects, not direct instances of them.

Then do so called "forward" declarations of the classes:

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

Of course, it would be better to use smart pointers rather than raw ones.

didierc
  • 14,572
  • 3
  • 32
  • 52
pm100
  • 48,078
  • 23
  • 82
  • 145
3

Just think about it:

  1. Each Object contains a Line;
  2. Each Line is an Object;
  3. Therefore, each Object contains an Object;
  4. And of course that Object contains in turn an Object;
  5. Which contains an Object... and so on until you get tired.

This is an attempt to set up an infinitely recursive data structure, and you can probably see why it is not allowed.

Instead, use forward declarations and (smart) pointers (unique_ptr<> seems to be the best choice here) to break the mutual dependency and allow for a termination to the recursive structure (pointer can be 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();
};
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
3

My guess is that you want any object to be either a primitive graphical object, like a line or a circle, or a compound object, ie. an object containing several others.

Your are actually almost there: what you should do is:

  • remove the Object subclasses instances from Object (see other answers for the reason behind this being a design mistake),

  • create a fourth class inheriting of Object:

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

Now if you want to manipulate in a generic way a list of objects, it's easy. All you need is to define the ad-hoc virtual methods on Object, and override them in the subclasses (for instance a draw method).

See this tutorial on polymorphism for more explanations on the concept.

didierc
  • 14,572
  • 3
  • 32
  • 52
1

You can NOT do what you've just described. The base class must not contain classes that derive from it. When a class derives, it contains all the components of the baseclass. So in your example, Object contains a Line and a Circle. A Circle contains Object which contains Circle and Line - you can see that we can to on just like the number of 3's in 1/3 ...

You can either have a reference or a pointer to an object of class Line or Circel, e.g.

class Line;
class Circle

You need the above lines BEFORE the Object class - it tells the compiler "There is a class Line and a class Circle. I'll come to what they actually contain later..."

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


protected:

   int x;
   int y;
private:
  Line* l;
  Circle* c;
}; 
Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
0

In order for a member variable to be of a given type (like 'Circle c') the class definition must have already appeared in the translation unit. So, in this case, what you're asking is impossible.

However, a pointer to an object only requires the compiler to know that a symbol (such as 'Circle') represents a class. You can do this by a forward class declaration. So an option is

class Circle;
class Line;

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

class Line: public Object { ... }

class Circle: public Object { ... }
Community
  • 1
  • 1
medgno
  • 188
  • 1
  • 5
0

In your code an Object object contains a Circle sub-object (data member) which in turn contains an Object sub-object (base class sub-object), which…

That yields infinite size, which is rather ungood.

However, the solution is very simple: don't derive those classes from Object.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331