Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling protected ctor of inheriting class from within static template method of base class fails

I have a component class that defines a static template method of how a Component should be created in general:

class Component {
protected:
    uint32_t id;

    Component(uint32_t id) :
            id(id) {
    }

    template<typename T, uint32_t C>
    static T* createComponent() {
        // content here not relevant
        return new T(someParameter);
    }

};

Then there is an implementation, for example a Button. The constructor of this class should not be used directly, instead there is a static method that calls the Component::createComponent template function.

class Button: public Component {
protected:
    Button(uint32_t id) :
            Component(id) {
    }
public:
    static Button* create();
};

The implementation looks like this, passing the type to instantiate and a constant thats used in creation:

Button* Button::create() {
    return createComponent<Button, UI_COMPONENT_BUTTON>();
}

Now the problem is, that the compiler complains with "error: 'Button::Button(uint32_t)' is protected". For my understanding, this constructor call should be OK as Button extends Component, but this seems to be a problem here.

How can I solve this?

like image 282
maxdev Avatar asked Dec 17 '14 15:12

maxdev


2 Answers

Since your create() function won't be able to deal with further inherited classes you can take advantage of this and not create a Button but, instead, a generic derived, protected, derived class which would have access to your protected constructor:

class Component {
    uint32_t id;
    template <typename T>
    struct Concrete: T {
        Concrete(uint32_t id): T(id) {}
    };
protected:
    Component(uint32_t id) :
        id(id) {
    }

    template<typename T, uint32_t C>
    static T* createComponent() {
        // content here not relevant
        return new Concrete<T>(C);
    }
};

class Button:
    public Component {
protected:
    Button(uint32_t id): Component(id) {}
public:
    static Button* create() {
         return createComponent<Button, UI_COMPONENT_BUTTON>();
    }
};
like image 63
Dietmar Kühl Avatar answered Oct 09 '22 10:10

Dietmar Kühl


Access specifier of Button constructor is protected that means it can only be accessed by classes derived from Button. If you want your code to work then you have to make that constructor public.

like image 2
ravi Avatar answered Oct 09 '22 11:10

ravi