Won Young Lee
Won Young Lee

Reputation: 165

C++ member initialization from derived class to base class

Let's see the following C++ codes. Each inherited class has its member variables and initialization function. These member variables are some different(almost same type) between inherited classes. Is there any good way to move (or merge) this initialization into base class?

class Base {
public:
   virtual init() = 0;
}
class A: public Base {
public:
   int a1;
   void init() { a1 = 0;}
}
class B: public Base {
public:
   int b1;
   void init() { b1 = 1;}
}

Upvotes: 0

Views: 1626

Answers (4)

Simon.Geng
Simon.Geng

Reputation: 1

Maybe you could use the template class skills to solve the problem. Like:

template <typename T> class Base {
public :
  virtual void init( T t ) = 0;
};

class A: public Base<T> {
public:
   T a1;
   void init( T t ) { a1 = t;}
}

class B: public Base<T> {
public:
   T b1;
   void init( T t ) { b1 = t;}
}

You could have a try.

Upvotes: -1

Disillusioned
Disillusioned

Reputation: 14832

No. Base has no knowledge of A::a1 or B::b1. More importantly it should not have any knowledge of it's subclass members as this leads to a fundamental breakdown of the encapsulation you're trying to achieve in the first place.

The best you can do is have your Base class define a virtual method for initialisation and control when that method is called. It is up to each subclass to override the method and ensure that when initialisation is needed it is performed according to each subclass's respective requirements.

One thing to note is that if your initialisation is intended to be once-off for the lifetime of each object, the the correct place to do this is using constructors as per koizyd's answer.


On a related note, I'd like to point out that what you're asking is a variation on one of the most common OO design flaws I've seen in my career.

Using inheritance for code reuse not encapsulation.

Basically you're trying to push functionality into the base class (for reuse), and all this really achieves is making the Base class large, top-heavy and unmaintainable.

Upvotes: 4

21koizyd
21koizyd

Reputation: 1993

In C++ we can't (almost always) create function init, we use constructors e.g

class Base {
};
class A : public Base {
public:
    int a1;
    A():Base(), a1(0) {}
};
class B : public Base {
public:
    int b1;
    B():Base(), b1(1){}
};

Construct "child" is A():Base(),a1(0), it's initializer list (:Base(),a1(0)), which create Base object, and int b1. You should remember about ; after class.

Upvotes: 1

Ken Y-N
Ken Y-N

Reputation: 15009

I'd probably structure code like this:

class Base {
public:
   void init() { sub_init(); }
protected:
   virtual void sub_init() = 0;
}
class A: public Base {
public:
   int a1;
protected:
   void sub_init() { a1 = 0;}
}
class B: public Base {
public:
   int b1;
protected:
   void sub_init() { b1 = 1;}
}

The alternative of doing something like (syntax probably not correct...):

class Base {
public:
   virtual void init() = 0;
protected:
   void generic_init<T>(T &foo, T const &bar) { foo = bar; }
}
class A: public Base {
public:
   int a1;
   void init() { generic_init<int>(a1, 0); }
}
class B: public Base {
public:
   int b1;
   void init() { generic_init<int>(b1, 1); }
}

Looks awful to me!

Upvotes: -1

Related Questions