受保护的构造函数有哪些实际用途?

发布于 2024-07-25 15:30:36 字数 54 浏览 8 评论 0原文

为什么有人会声明构造函数受保护? 我知道构造函数被声明为私有,目的是不允许它们在堆栈上创建。

Why would anyone declare a constructor protected? I know that constructors are declared private for the purpose of not allowing their creation on stack.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

゛时过境迁 2024-08-01 15:30:36

当一个类是(旨在作为)抽象类时,受保护的构造函数是完全正确的。 在这种情况下,您不希望从类实例化对象,而只想使用它来继承。

还有其他用例,例如某些构造参数集应仅限于派生类。

When a class is (intended as) an abstract class, a protected constructor is exactly right. In that situation you don't want objects to be instantiated from the class but only use it to inherit from.

There are other uses cases, like when a certain set of construction parameters should be limited to derived classes.

一杆小烟枪 2024-08-01 15:30:36

当存在无法仅由构造函数保证的构造要求时,非公共构造函数非常有用。 例如,如果需要在构造函数之后立即调用初始化方法,或者如果对象需要向某个容器/管理器对象注册自身,则必须在构造函数之外完成此操作。 通过限制对构造函数的访问并仅提供工厂方法,您可以确保用户收到的任何实例都将满足其所有保证。 这也常用于实现 Singleton,这实际上只是类所做的另一个保证(只有一个实例)。

将构造函数设置为受保护而不是私有的原因与将任何其他方法或字段设置为受保护而不是私有的原因相同:以便它可以由子级继承。 也许您需要基类中的公共非虚拟工厂方法,该方法返回对派生类实例的引用; 派生类显然想要访问父构造函数,但您仍然不希望在工厂之外创建它们。

Non-public constructors are useful when there are construction requirements that cannot be guaranteed solely by the constructor. For instance, if an initialization method needs to be called right after the constructor, or if the object needs to register itself with some container/manager object, this must be done outside the constructor. By limiting access to the constructor and providing only a factory method, you can ensure that any instance a user receives will fulfill all of its guarantees. This is also commonly used to implement a Singleton, which is really just another guarantee the class makes (that there will only be a single instance).

The reason for making the constructor protected, rather than private, is the same as for making any other method or field protected instead of private: so that it can be inherited by children. Perhaps you want a public, non-virtual factory method in the base class, which returns references to instances of the derived classes; the derived classes obviously want access to the parent constructors, but you still don't want to be creating them outside of your factory.

把回忆走一遍 2024-08-01 15:30:36

当类的方法都不是纯虚拟的时,受保护的构造函数可用于使类有效地抽象。

从 C++ 意义上来说,它并不是很抽象,因为友元类仍然可以使用它而无需重写,但是您必须声明它们。

A protected constructor can be used to make a class effectively abstract when none of its methods are pure-virtual.

It is not quite abstract in the C++ sense since friend classes can still use it without overriding, but then you would have to declare these.

魂归处 2024-08-01 15:30:36

受保护的构造函数意味着只有派生成员才能使用该构造函数构造类的实例(以及派生实例)。 这听起来有点先有鸡还是先有蛋的问题,但有时在实现类工厂时很有用。

A protected constructor means that only derived members can construct instances of the class (and derived instances) using that constructor. This sounds a bit chicken-and-egg, but is sometimes useful when implementing class factories.

星星的軌跡 2024-08-01 15:30:36

一种用途可能是工厂模式

one use could be factory patterns

一萌ing 2024-08-01 15:30:36

对于有副作用的工厂方法。

class mine {

  private:
    mine () {};

  protected:
    mine(int id) : m_id(id) {};

   int m_id;
   static int m_count;

  public:
    static mine* CreateOneOfMe() {
         return mine(m_count++);
    }

    int GetId() { return m_id; }

 };

这将创建该类的实例并保证每个实例都有一个唯一的递增整数 id。 请注意,如果您要使用的构造函数不是默认构造函数,则也必须隐藏默认构造函数。

For factory methods with side-effects.

class mine {

  private:
    mine () {};

  protected:
    mine(int id) : m_id(id) {};

   int m_id;
   static int m_count;

  public:
    static mine* CreateOneOfMe() {
         return mine(m_count++);
    }

    int GetId() { return m_id; }

 };

This creates instances of the class and guarantees that each of them has a unique incrementing integer id. Note that if the constructor you want to use is not the default, you must hide the default too.

一杆小烟枪 2024-08-01 15:30:36

让子类使用实例化器不能直接访问的构造函数。

To let a subclass use a constructor that should not be accessible to an instantiator directly.

你的心境我的脸 2024-08-01 15:30:36

您可以使用它来限制可以创建它的类,例如:

class Level
{
private:

 Level();
 ~Level();

 friend class LevelManager;
};

唯一可以创建它的实例的类是 LevelManager 类,因此您将始终知道 Level 实例是在 LevelManager 中创建的。

You could use it to limit the classes that could create it, for example:

class Level
{
private:

 Level();
 ~Level();

 friend class LevelManager;
};

The only class that can create an instance of it is the LevelManager class, so you will always know that the Level instance is created in the LevelManager.

短暂陪伴 2024-08-01 15:30:36

protected 构造函数的一种用途是实现 CRTP 模式,请参见下面的代码:

#include <iostream>
#include <assert.h>

template <class T>
class ComparableMixin {
public:
    bool operator !=(ComparableMixin &other) {
        return ~(*static_cast<T*>(this) == static_cast<T&>(other));
    }
    bool operator <(ComparableMixin &other) {
        return ((*(this) != other) && (*static_cast<T*>(this) <= static_cast<T&>(other)));
    }
    bool operator >(ComparableMixin &other) {
        return ~(*static_cast<T*>(this) <= static_cast<T&>(other));
    }
    bool operator >=(ComparableMixin &other) {
        return ((*static_cast<T*>(this) == static_cast<T&>(other)) || (*(this) > other));
    }
protected:
    ComparableMixin() {}
};

class Integer: public ComparableMixin<Integer> {
public:
 Integer(int i) {
     this->i = i;
 }
 int i;
 bool operator <=(Integer &other) {
     return (this->i <= other.i);
 }
 bool operator ==(Integer &other) {
     return (this->i == other.i);
 }
};
int main() {

    Integer i(0) ;
    Integer j(1) ;
    //ComparableMixin<Integer> c; //compilation error!
    assert (i < j );
    assert (i != j);
    assert (j >  i);
    assert (j >= i);

    return 0;
}

One use of protected constructor is to implement the CRTP pattern, see the code below:

#include <iostream>
#include <assert.h>

template <class T>
class ComparableMixin {
public:
    bool operator !=(ComparableMixin &other) {
        return ~(*static_cast<T*>(this) == static_cast<T&>(other));
    }
    bool operator <(ComparableMixin &other) {
        return ((*(this) != other) && (*static_cast<T*>(this) <= static_cast<T&>(other)));
    }
    bool operator >(ComparableMixin &other) {
        return ~(*static_cast<T*>(this) <= static_cast<T&>(other));
    }
    bool operator >=(ComparableMixin &other) {
        return ((*static_cast<T*>(this) == static_cast<T&>(other)) || (*(this) > other));
    }
protected:
    ComparableMixin() {}
};

class Integer: public ComparableMixin<Integer> {
public:
 Integer(int i) {
     this->i = i;
 }
 int i;
 bool operator <=(Integer &other) {
     return (this->i <= other.i);
 }
 bool operator ==(Integer &other) {
     return (this->i == other.i);
 }
};
int main() {

    Integer i(0) ;
    Integer j(1) ;
    //ComparableMixin<Integer> c; //compilation error!
    assert (i < j );
    assert (i != j);
    assert (j >  i);
    assert (j >= i);

    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文