iammilind
iammilind

Reputation: 69988

How to make base class's certain constructor be callable only by particular derived class(es)?

struct Base {
  Base (type1, type2, type3);
  Base (); // <--- should be invoked only by `Derived_2`
  virtual ~Base() = 0;  // an abstract class
};

Say for above Base, we have multiple derived classes: Derived_1, Derived_2, ..., Derived_N.

While constructing an object, all derived classes must invoke Base(type1, type2, type3) constructor, except Derived_2, which should use Base() (the default constructor) while constructing the object.

Is there a way (C++11 is ok) to have such rule? In other words if anyone other than Derived_2 tries to use the default no argument constructor then compiler should give an error.

Edit: For those who are asking about the design problem, I agree with that. Here is my take on it.

I hope this makes the idea clear.

Upvotes: 1

Views: 1141

Answers (4)

Rabbiya Shahid
Rabbiya Shahid

Reputation: 422

When you are writing the derived classes, then in only the second derived class should you call the default base constructor in the rest you can call the parameterised constructor.

      class derived1{             
                     derived1(): base(type1, type2, type3){}

                     };

       class derived2{
                      derived2(): base(){}
                      };
        class derived3{             
                     derived3(): base(type1, type2, type3){}

                     };
       class derived4{             
                     derived4(): base(type1, type2, type3){}

                     };

`

and so on. For the rest of the classes. Also... this is oop, you make the classes so you decide the behaviour of the classes yourself. Therefore you just make sure that the default constructor for base class isn't called anywhere in the derived classes explicitly. Everytime you need to call a constructor, you call the parameterised one in the derived classes, since afterall, you cnotrol the working of the class.

Upvotes: 0

Julien-L
Julien-L

Reputation: 5416

I would introduce another level of derivation:

        Base
         ^
         |
   +-----+------+
   |            |
Derived2    BaseWithParams
              ^         ^
              |         |
           Derived1    DerivedN

In the base, you implement no state or a default state (seems to me it makes sense to have a default state, since this is why Derived2 was supposed to do).

struct Base
{
    virtual ~Base() = 0;
};
struct Derived2 : public Base
{
    Derived2() {}          // Do default initialization
    virtual ~Derived2() {} // Implement destructor so it's not pure virtual anymore
};
struct BaseWithCtor : public Base
{
    BaseWithCtor(type1, type2, type3) {}
    // Do not implement destructor, leave the class abstract
};

Upvotes: 4

jtepe
jtepe

Reputation: 3350

The only way I can think of is declaring your Base's default constructor private and making Derived_2 a friend of your Base class, so it can call its default contructor.

However, this style is horrible, since your Base class now has to know about one of its derived classes. And it is still possible for Dervived_2 to call the constructor with 3 parameters.

Upvotes: 7

Jerry Coffin
Jerry Coffin

Reputation: 490178

Make the default constructor private, and declare Derived_2 as a friend:

class Derived_2;

class Base { 
    Base();
public:
    Base(int, int, int);
    virtual ~Base() = 0;
    friend class Derived_2;
};

class Derived_1 : public Base { 
public:
    Derived_1() : Base(1, 2, 3) {}
};

class Derived_1a : public Base { 
public:
    Derived_1() {} // will fail: Base::Base() not accessible
};


class Derived_2 :public Base { 
public:
   ~Derived_2() {}
};

Upvotes: 2

Related Questions