简体   繁体   English

从基础 class 中的 static 工厂方法访问受保护的构造函数

[英]Access to protected constructor from static factory method in base class

I've got a static factory method in a base class.我在基础 class 中有一个 static 工厂方法。 Because of some reasons I want to each derived class will be instantiated by this factory method hence all these classes have protected ctors.由于某些原因,我希望每个派生的 class 都将由此工厂方法实例化,因此所有这些类都具有受保护的 ctor。

In real situation the Create function does more additional logic along with error handling.在实际情况下,Create function 执行更多附加逻辑以及错误处理。

class Base
{
public:
    virtual ~Base() {}

    template <typename T>
    static void Create(std::unique_ptr<T>& pOut)
    {        
        pOut = std::unique_ptr<T>(new T);
        // ... 
    }
protected:
    Base() {}
};

class Derived : public Base
{
protected:
    Derived() {}
};

int main()
{
    std::unique_ptr<Derived> ptr;
    Derived::Create(ptr);
}

That code obviously doesn't compile since we don't have access to the protected ctor.该代码显然无法编译,因为我们无权访问受保护的 ctor。

prog.cc: In instantiation of 'static void Base::Create(std::unique_ptr<_Tp>&) [with T = Derived]':
prog.cc:33:24:   required from here
prog.cc:17:35: error: 'Derived::Derived()' is protected within this context
   17 |         pOut = std::unique_ptr<T>(new T);
      |                                   ^~~~~
prog.cc:26:5: note: declared protected here
   26 |     Derived() {}
      |     ^~~~~~~

The first solution that seems to be the most common is friend declaration in derived class.第一个似乎最常见的解决方案是派生 class 中的友元声明。 However it works I don't like it because:但是它有效,我不喜欢它,因为:

  1. I have to add such declaration in each derived class我必须在每个派生的 class 中添加这样的声明
  2. This is a friend这是一个朋友
class Derived : public Base
{
protected:
    Derived() {}
    friend void Base::Create<Derived>(std::unique_ptr<Derived>&);
};

Thinking about more generic approach I was trying something like this:考虑更通用的方法,我正在尝试这样的事情:

 template <typename T>
    static void Create(std::unique_ptr<T>& pOut)
    {
        static_assert(std::is_base_of_v<Base, T>, "T should be Base-family class.");
        class CreateHelper : public T
        {
            public:
                static void InternalCreate(std::unique_ptr<T>& pOut)
                {
                    pOut = std::unique_ptr<CreateHelper>(new CreateHelper);
                    // ... 
                }
        };
        
        CreateHelper::InternalCreate(pOut);
    }

It works but looks weird to me and:它有效,但对我来说看起来很奇怪,并且:

  1. The real pointer type is CreateHelper however outside this function we don't see that真正的指针类型是 CreateHelper 但是在这个 function 之外我们看不到
  2. This approach needs that Base-familiy should be polimorphic since we use pointer to base class (it's seems this condition should be always met but still it's worth to mention about that)这种方法需要 Base-familiy 应该是多态的,因为我们使用指向基本 class 的指针(似乎应该始终满足这个条件,但仍然值得一提)

My questions are我的问题是

  1. What do you think about the last approach?您如何看待最后一种方法?
  2. Is it considered as a bad design?它被认为是一个糟糕的设计吗?

In general, a far better approach here is to simply refer to simple construction helper classes, then you can refer to make_unique() too:一般来说,这里更好的方法是简单地引用简单的构造辅助类,然后你也可以引用 make_unique() :

class Base
{
protected:
    struct Accessor
    {
      explicit Accessor() = default;
    };
 
public:
    Base(Accessor) {}
    virtual ~Base() {}

    template <typename T>
    static void Create(std::unique_ptr<T>& pOut)
    {        
        pOut = std::make_unique<T>(Accessor());
        // ... 
    }
};

class Derived : public Base
{
public:
    Derived(Accessor) : Base(Accessor()) {}
};

Only drawback: Derived classes have to adapt their constructor(s) accordingly.唯一的缺点:派生类必须相应地调整其构造函数。

A general point: A factory should almost always be aware of its relevant types in general, at least of partial aspects of the relevant types, provided by polymorphism (interfaces) or/and via traits.一般观点:工厂应该几乎总是知道它的相关类型,至少是相关类型的部分方面,由多态性(接口)或/和通过特征提供。 So I think, this is a bit more convenient:所以我认为,这更方便一点:

template <class T, typename std::enable_if<std::is_base_of<Base, T>::value>::type* = nullptr>
static void Create(std::unique_ptr<T>& pOut)
{        
    pOut = std::make_unique<T>(Accessor());
    // ... 
}

Further on: You might have to rethink about your general creation design here.进一步:您可能必须在这里重新考虑您的一般创作设计。 The common approach here is to return the created object, not to fill a reference.这里常用的做法是返回创建的object,而不是填写引用。 With your current approach, you have to think about exception safety (contracts..) here at least twice for instance...使用您当前的方法,您必须在这里至少考虑两次异常安全(合同......),例如......

Possible approach:可能的方法:

template <class T, typename std::enable_if<std::is_base_of<Base, T>::value>::type* = nullptr>
static std::unique_ptr<T> Create()
{        
    auto pOut = std::make_unique<T>(Accessor());
    // ... 

    return pOut;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 访问受保护的基类构造函数 - Access to protected constructor of base class 基本访问中的工厂方法保护ctor in derived - Factory method in base access protected ctor in derived 如何从派生类访问基类中的受保护方法? - How to access protected method in base class from derived class? 从基类的静态模板方法中调用继承类的受保护的ctor失败 - Calling protected ctor of inheriting class from within static template method of base class fails 我可以从派生类中的静态函数访问基类受保护的成员吗? - Can I access a base classes protected members from a static function in a derived class? 派生类中的静态方法可以在C ++中调用受保护的构造函数吗? - Can a static method in a derived class call a protected constructor in C++? 派生带有静态方法(又称工厂)的类,该方法以基类为模板 - Deriving a class with a static method (aka. Factory), templated with the Base class 派生类无法访问基类的受保护方法 - Derived class can't access protected method of base class 使用派生类的朋友提供的基类的受保护静态函数 - Use protected static function of the base class from the friend of the derived class 静态基础构造函数的设计模式,该模型在最终类中调用静态方法 - Design pattern for static base constructor that calls static method in final class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM