Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: How to enforce derived class to set base member variables?

I have a base class with a member variable (preferably private) and I need to enforce derived classes to initialize it with a value based on their implementation; much like a pure virtual function.

To clarify, I want to declare a member in Base, have derived classes initialize it, and if they don't they get a compiler error. In the following code, I declared default constructor of Base to be protected. Then declared default constructor of Derived to be private.

class Base {
private:
    int _size;

protected:
    Base(){}
    /* pure virtual methods */

public:
    Base(int size) : _size(size){} // must enforce derived to call this.
    virtual ~Base(){}

    /* more pure virtual methods */
};

class Derived : public Base {
private:
    Derived() {}
public:
    Derived(int size) : Base(size) {
        //Base::Base(size);
    }
};

int main()
{
    Derived* d1 = new Derived();    // throws an error as needed: 
                                    // "Cannot access private member declared in class 'Derived'"

    Derived* d2 = new Derived;      // throws an error as needed: 
                                    // "Cannot access private member declared in class 'Derived'"

    Derived* d3 = new Derived(5);   // works as needed

    return 0;
}

The problem with the above code is that if another definition of Derived doesn't hide the default constructor. I'm still stuck with an uninitialized Base::_size.

I don't know if there is another way to go about this other than inheritance, because I still need derived classes to implement their own behavior for several methods declared in Base.

Any pointers are appreciated.

like image 818
mbadawi23 Avatar asked Oct 20 '22 23:10

mbadawi23


1 Answers

After the confusion about calling a base class ctor and default ctors, maybe the solution is just to not have a default ctor in Base?

class Base {
private:
    int _size;

public:
    // no default ctor
    Base(int size) : _size(size) {} // must enforce derived to call this.
    virtual ~Base(){}

    /* more pure virtual methods */
};

class Derived : public Base {
public:
    // no default ctor
    Derived(int size) : Base(size){
    }
    // examplary default ctor:
    //Derived() : Base(42) {}
};

int main()
{
    Derived d1;                   // error: no default ctor
    Derived* d2 = new Derived;    // same, but why use the free store?

    Derived d3(5);                // works as needed
    Derived* d4 = new Derived(5); // same, but why use the free store?

    return 0;
}

To be explicit about not having a default ctor, one could use

class Base {
    /* ... */
    Base() = delete;
    /* ... */
};
like image 129
dyp Avatar answered Nov 15 '22 07:11

dyp