Xun Yang
Xun Yang

Reputation: 4419

How to initialize member objects that requires constructor parameters in derived classes?

I would like to include a Composed object in my Base class, and have different derived classes have different configurations of it. However the Composed class requires parameter in constructor, and I don't have control over its architecture.

The compiler is reporting an error because the parameter for Composed should be passed at the initialization of Base class. But I only want it to be initialized in derived classes. What should I do in this case?

class Base{
  public:
    Base(); //Error
  protected:
    Composed comp;
};
class Composed{
  public:
    Composed(int id):id(id);
  private:
    int id;
};
class Derived_1:public Base{
  public:
    Derived():comp(1234){};
};    
class Derived_2:public Base{
  public:
    Derived():comp(2345){};
};   

Upvotes: 1

Views: 245

Answers (3)

texasflood
texasflood

Reputation: 1633

Imagine you constructed a Base object. How would it know what parameter to pass to comp's constructor? The Base class is fundamentally flawed, that's why you have an error. It needs to know how to construct it's Composed member object.

You can add a default constructor for Composed, and then modify this object in Derived_1 and Derived_2. Alternatively, as others suggested, you can make Base's constructor take the parameters to construct comp. This sounds preferable to me, but it depends on your use case.

Remember that when you are constructing Derived_1 or Derived_2, the Base class is the first thing that is created, before other member variables.

Upvotes: 2

Rob L
Rob L

Reputation: 2530

There are a few options. The most straightforward is to pass the objects required to build Comp to the Base class constructor.

class Base{
  public:
    Base(int id):comp(id){}
protected:
    Composed comp;
};

class Derived_1:public Base{
  public:
    Derived():Base(1234){}
};    
class Derived_2:public Base{
  public:
    Derived():Base(2345){}
};   

Another possibility is not to include Comp in the base class. Put it in each derived class. You can add a pure virtual function to the Base class that returns Comp (or its address).

One more option is to store a pointer to Comp (perhaps a unique_ptr) and allocate it in the derived classes.

Upvotes: 1

H. Guijt
H. Guijt

Reputation: 3375

You'll have to pass that parameter up to Base, and then hand it down to comp:

class Composed{
  public:
    Composed(int id):id(id);
  private:
    int id;
};
class Base{
  public:
    Base(int id):comp(id){}
  protected:
    Composed comp;
};
class Derived_1:public Base{
  public:
    Derived():Base(1234){};
};    
class Derived_2:public Base{
  public:
    Derived():Base(2345){};
}; 

Upvotes: 4

Related Questions