C++ 从基类的静态模板方法内调用继承类的受保护构造函数失败
我有一个component类,它定义了一个静态模板方法,说明了通常应该如何创建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
组件
:
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>();
}
};