jodag
jodag

Reputation: 22184

Is it possible to defer member variable initialization to inherited class without modifying the parent class?

I'm having a specific problem which I've converted into the following Minimal, Complete, and Verifiable example.

#include <iostream>

class Foo {
    public:
        Foo(int v) : val(v) {}

        int get_val() const
        {
            return val;
        }

    private:
        int val;
};

class Parent {
    public:
        Parent() : member(0) {}

        const Foo& get_member() const
        {
            return member;
        }

    protected:
        Foo member;
};

// Nothing above this line should be changed

class Child : public Parent
{
    public:
        // This doesn't work (compile error)
        //Child() Parent::member(1) {}

        // Nor does this (also a compile error)
        //Child() this->member(1) {}
};

int main()
{
    Child x;
    std::cout << x.get_member().get_val() << std::endl;
    return 0;
}

This example demonstrates the issue I'm having in a larger software project where I'm inheriting from an external library but need to directly initialize one of the parent's member variables.

Unfortunately, the Parent class does not have a constructor which parameterizes its member's initialization.

If the Parent class had a constructor of the form

Parent(int val) : member(val) {}

then I could write a Child constructor as

Child() Parent::Parent(1) {}

but that is not the case for me.

Question: Is it possible to defer the initialization of a parent's member variable to an inherited class? If so, how?

Upvotes: 3

Views: 739

Answers (2)

user0042
user0042

Reputation: 8018

The easiest way is to initialize Parent::member in the Child class constructor body (again):

class Child : public Parent
{
    public:
        Child() {
            Parent::member = 1;
        }

};

See the live demo.


As it was clarified in comments, you aren't supposed to assign the Parent::member variable.

In such case (let's assume the design was at least something useful), you usually have the ability to apply a setter for certain properties of the parent class member's instance:

class Foo {
    Foo(const& Foo) = delete;
    Foo& operator=(const& Foo) = delete;
public:
    Foo() = default;
    int property() const;
    void property(int newVal);
};

class Parent {
protected:
    Foo member;
public:
    Parent() = default;
};

class Child : public Parent {
public:
    Child() {
        Parent::member.property(1);
    };
};

Upvotes: 1

R Sahu
R Sahu

Reputation: 206567

Is it possible to defer the initialization of a parent's member variable to an inherited class? If so, how?

The parent class's member variable is either initialized in its member initialization list or in the body of the constructor. The child class cannot initialize the parent class's member variable in its initializer list -- that is not allowed by the language. The best you can do, it seems, is to set the value of the parent class's member in the body of the child class's constructor.

Example:

struct foo
{
   int a;
};

struct bar : foo
{
   bar() : a(0) {} // Not allowed
};

but

struct bar : foo
{
   bar() { a = 0; } // Allowed
};

Upvotes: 4

Related Questions