-1

Can I have a class ("BIG") which has another class as a member (of type "Base"), so that upon construction, this "Base" member will actually be set to a derived class?

In particular, I want to have

class Base{
  public:
    void dostuff(){};
};

class DerivedA : public Base{
  public:
    void dostuff(){
     //implementation version A 
    }
};


class DerivedB : public Base{
  public:
    void dostuff(){
     //implementation version B 
    }
};

class BIG{
 Base mything;

 BIG(int Type){
  if (Type==0)
   mything=DerivedA();
  if (Type==1)
   mything=DerivedB();
 }
};

Does C++ not allow this. In particular, I would be "Downcasting" mything from a Base to a DerivedA or a DerivedB. Am I correct that Downcasting is only allowed from Base pointers to Derived pointers, and only when the Base pointer is actually already a pointer to a Derived class?

Wes
  • 35
  • 3
  • 1
    Yes of course that's possible. Please clarify what's your particular problem doing so. Did you mean to use a reference or pointer member rather than a sliced instance? – πάντα ῥεῖ Feb 06 '19 at 21:21
  • 4
    It doesn't look like you have any inheritance anywhere...did you forget to add it in your example? – scohe001 Feb 06 '19 at 21:21
  • 1
    You need to use a pointer or a reference. These thing are specially designed to point/refer to objects of a derived class. (Provided you do actually have a derived class; there isn't any in the posted code) – n. m. could be an AI Feb 06 '19 at 21:21
  • There is no downcasting anywhere here...? `Base* mything = new DerivedA();` would be a classical polymorphism, where you assign a derived class object to a base class pointer. `BIG` looks like an implementation of Factory pattern (or a flavour of it). – Yksisarvinen Feb 06 '19 at 21:24

2 Answers2

0

First, you probably forgot to actually derive from Base. But anyway, polymorphism requires a pointer or a reference. Otherwise, assigning an object of a derived class to a variable of the base class' type will "slice" the derived class object, i.e. it will cut a base class object out of the derived class object:

class Base{
  public:
    virtual void dostuff(){ cout << "in base" << endl; };
};

class DerivedA : public Base {
  public:
    virtual void dostuff(){ cout << "in derived" << endl; };
};

int main() {

  Base mything = DerivedA();  // slicing, will result in a `Base`-object
  mything.dostuff(); // Base class implementation

  Base *polymorph = new DerivedA(); // polymorphic; will point to a DerivedA-instance
  polymorph->dostuff(); // DerivedA class implementation of dostuff



}
Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
  • 1
    " polymorphism requires a pointer or a reference" is exactly what I was missing. – Wes Feb 06 '19 at 21:37
0

Yes, this is possible, but mything must be a pointer or a reference to a polymorphic object. If you keep it as a plain object, you would have slicing.

class BIG{
    Base *mything;

public: 
    BIG(int Type){
        if (Type==0)
           mything = new DerivedA();
        else if (Type==1)
           mything = new DerivedB();
    }
};

Of course, this suppose that both DerivedA and DerivedB inherit publicly from Base. If you want the right dostuff() function to be called, you also need to make it virtual (this is not specific to your problem, but to polymorphic classes), as well as have a virtual destructor.

Finally, you'd need to take care of the rule of 3 if you don't want to suffer from nasty allocation/deallocation errors. A more convenient alterative is therefore to use a smart pointer instead of a raw pointer and let the smart pointer take care of copies, and destruction.

Comment: it's a question of style which is irrelevant here, but try to take the good habits and avoid an all cap class name ;-)

Christophe
  • 68,716
  • 7
  • 72
  • 138