Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从基类的静态模板方法内调用继承类的受保护构造函数失败_C++_Templates_Inheritance_Protected - Fatal编程技术网

C++ 从基类的静态模板方法内调用继承类的受保护构造函数失败

C++ 从基类的静态模板方法内调用继承类的受保护构造函数失败,c++,templates,inheritance,protected,C++,Templates,Inheritance,Protected,我有一个component类,它定义了一个静态模板方法,说明了通常应该如何创建组件: class Component { protected: uint32_t id; Component(uint32_t id) : id(id) { } template<typename T, uint32_t C> static T* createComponent() { // content here no

我有一个component类,它定义了一个静态模板方法,说明了通常应该如何创建
组件

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

};
实现如下所示,传递要实例化的类型和创建中使用的常量:

Button* Button::create() {
    return createComponent<Button, UI_COMPONENT_BUTTON>();
}
按钮*按钮::创建(){
返回createComponent();
}
现在的问题是,编译器抱怨“error:'Button::Button(uint32_t)'is protected”。据我所知,当
按钮
扩展
组件
时,这个构造函数调用应该是正常的,但这似乎是一个问题


如何解决此问题?

按钮构造函数的访问说明符受到保护,这意味着它只能由从按钮派生的类访问。如果你想让你的代码正常工作,那么你必须公开这个构造函数。

“Button”扩展了“Component”,所以“Button”可以访问“Component”的受保护成员,但是“Component”不知道“Button”,所以不能访问它的受保护成员。

因为你的
创建()
函数将无法处理进一步继承的类。您可以利用这一点,不创建
按钮,而是创建一个可以访问
受保护的
构造函数的通用派生、受保护的派生类:

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>();
    }
};
类组件{
uint32_t id;
模板
结构混凝土:T{
混凝土(uint32_t id):t(id){}
};
受保护的:
组件(uint32\u t id):
身份证{
}
模板
静态T*createComponent(){
//此处的内容不相关
返回新混凝土(C);
}
};
类别按钮:
公共部分{
受保护的:
按钮(uint32_t id):组件(id){
公众:
静态按钮*创建(){
返回createComponent();
}
};

标题的复杂性让我抓狂,但这是一个好问题。我无法想象一个更容易描述基本问题的问题:驻留,你的构造函数没有做“创建”方法无法做的事情,所以不要使用任何Ctor?问题是还有一个
窗口
类不使用
createComponent
函数,尽管我仍然想强制它将id传递给构造函数。但是,是的,您是对的,我可以将该逻辑添加到模板函数中。:)谢谢谢谢,我还以为遗产会一直延续下去呢。找到了另一个同样有效的解决方案:添加
friend类组件
按钮的类主体。正确<代码>受保护的
不授予对基类的访问权,只授予派生类…@maxdev:仅供记录:您绝对不必将构造函数
公开
,并且基于您编写的内容,您可能不想公开。虽然访问权限不向上,但您可以通过一个由基控制的派生类使用简单的委托来处理受保护的构造函数(参见,例如,我的答案)。不知道有点模糊,我可以让类知道。哇,很棒的解决方案!非常感谢。是的,
Base::createComponent()
当使用
ConcreteButton
调用时,实际上,das返回一个
Concrete*
。然而。用户调用
Button::create()
返回其基类:
Button*
。仔细想想,
base::createComponent()
实际上可以使用
按钮
并在内部创建一个
具体按钮
——这样派生类甚至不需要知道这个辅助类,它可以在
基中是私有的
!我将相应地更新代码。您也可以在
createComponent
中实例化
Concrete
,使其更容易:)注释竞态条件:D干得好,不会想到的:)
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>();
    }
};