Calling protected ctor of inheriting class from wi

2019-04-06 15:33发布

问题:

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?

回答1:

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>();
    }
};


回答2:

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.



回答3:

"Button" extends "Component", so "Button" can access protected members of "Component", but "Component" does not know about "Button", and so cannot access it's protected members.