受保护的构造函数的实际用途是什么?

时间:2009-06-29 08:41:37

标签: c++ constructor protected

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

9 个答案:

答案 0 :(得分:92)

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

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

答案 1 :(得分:9)

一种用途可能是工厂模式

答案 2 :(得分:9)

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

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

答案 3 :(得分:7)

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

在C ++意义上它并不是很抽象,因为朋友类仍然可以使用它而不会覆盖,但是你必须声明这些。

答案 4 :(得分:6)

受保护的构造函数意味着只有派生成员才能使用该构造函数构造类(和派生实例)的实例。这听起来有点鸡蛋和鸡蛋,但在实施班级工厂时有时很有用。

答案 5 :(得分:5)

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

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。请注意,如果要使用的构造函数不是默认构造函数,则必须隐藏默认构造函数。

答案 6 :(得分:4)

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

答案 7 :(得分:3)

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

class Level
{
private:

 Level();
 ¨Level();

 friend class LevelManager;
};

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

答案 8 :(得分:0)

受保护的构造函数的一种用法是实现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;
}