purga
purga

Reputation: 453

Using a base-class object to represent its derived-class objects

I need a way for a single variable to represent two kinds of objects derived from the same base class.

It's kinda hard to describe but I'll try the best:

Say the base class:

class Rectangle
{
   float w;
   float h;
   const float area() {return w*h;}
};

And the two derived classes:

class Poker : Rectangle
{
    int style;  // Diamond, Club, ....
    int point;  // A~10, J, Q, K
};

class BusinessCard : Rectangle
{
    string name;
    string address;
    string phone;
};

Now is it possible to declare an object, which could be either a poker or a business-card?

'cuz the usage below is illegal:

Rectangle* rec;
rec = new Poker();
delete rec;
rec = new BusinessCard();

Polymorphism might be a way but since it's only good for changing base-class' member attributes, I need this object to be able to represent exactly either of the derived objects.

EDIT:

Thanks for the all the answers. The public inheritance , the virtual destructor and even the boost::variant typedef are all fantastic hints.

Upvotes: 2

Views: 439

Answers (5)

Mehrdad Afshari
Mehrdad Afshari

Reputation: 421988

You can do that. The problem is the inheritance modifier for classes is private. Most of the time, private inheritance is not what you want to use. Instead, declare it explicitly as public:

class Rectangle
{
   float w;
   float h;
   const float area() {return w*h; }; // you missed a semicolon here, btw
   virtual ~Rectangle() { } // to make `delete` work correctly
};

class Poker : public Rectangle // note the public keyword
{
    int style;  // Diamond, Club, ....
    int point;  // A~10, J, Q, K
};

class BusinessCard : public Rectangle 
{
    string name;
    string address;
    string phone;
};

Then your code snippet should work.

Upvotes: 8

John Dibling
John Dibling

Reputation: 101456

Change the subclasses to use public derivation and your code works, with some cleanup. You should also use virtual destructors so the delete works correctly.

class Rectangle
{   
    float w;   
    float h;   
    const float area() 
    {
        return w*h;
    }
public:
    virtual ~Rectangle(){};
};

class Poker : public Rectangle
{    
    int style;  // Diamond, Club, ....    int point;  // A~10, J, Q, K
};

class BusinessCard : public Rectangle
{    
    string name;    
    string address;    
    string phone;
};

Upvotes: 1

TimW
TimW

Reputation: 8447

I need this object to be able to represent exactly either of the derived objects.

Don't know if I understand it correct but have a look at boost::variant

typedef boost::variant<Poker, BusinessCard> PokerOrBusinessCard

Now you can access the derived classes with a boost variant visitor class.

Maybe this can be a solution.

Upvotes: 2

Tobias Langner
Tobias Langner

Reputation: 10808

You need to change the qualifier for the inheritence to public.

class Poker : public Rectangle
{
    int style;  // Diamond, Club, ....
    int point;  // A~10, J, Q, K
};

class BusinessCard : public Rectangle
{
    string name;
    string address;
    string phone;
};

is what you want. Now both classes, BusinessCard and Poker are of type Rectangle.

Upvotes: 3

AlbertoPL
AlbertoPL

Reputation: 11509

I think what you may be looking for is multiple inheritance, where an object can sometimes be a Poker and sometimes a BusinessCard.

See here for a tutorial:

http://www.deitel.com/articles/cplusplus_tutorials/20060225/MultipleInheritance/index.html

Note that you can decide to make it one or the other if you wish, it does not have to be both all of the time, which may satisfy what you need.

Upvotes: 1

Related Questions