私有构造函数

52

2
请参见https://dev59.com/43I95IYBdhLWcg3w_zMN。 - StuartLC
很好地发现了,此问题的被接受答案对于C++是无用的 --> 在C++中创建一个静态函数类是不好的做法,我们不受“纯”面向对象编程思维的限制。 - Matthieu M.
https://dev59.com/43I95IYBdhLWcg3w_zMN#16547184 - Tunvir Rahman Tusher
7个回答

69

私有构造函数意味着用户无法直接实例化一个类。相反,您可以使用类似Named Constructor Idiom的方式创建对象,其中您可以使用static类函数来创建并返回类的实例。

命名构造函数习惯用于更直观地使用类。C++ FAQ中提供的示例是用于表示多个坐标系的类。

这是直接从链接中提取的信息。它是表示不同坐标系中点的类,但可以用于表示矩形和极坐标点,因此为了使用户更加直观,使用不同的函数来表示返回的Point代表哪个坐标系。

 #include <cmath>               // To get std::sin() and std::cos()

 class Point {
 public:
   static Point rectangular(float x, float y);      // Rectangular coord's
   static Point polar(float radius, float angle);   // Polar coordinates
   // These static methods are the so-called "named constructors"
   ...
 private:
   Point(float x, float y);     // Rectangular coordinates
   float x_, y_;
 };

 inline Point::Point(float x, float y)
   : x_(x), y_(y) { }

 inline Point Point::rectangular(float x, float y)
 { return Point(x, y); }

 inline Point Point::polar(float radius, float angle)
 { return Point(radius*std::cos(angle), radius*std::sin(angle)); }

已经有很多其他回答也符合为什么C++中会使用私有构造函数(其中包括Singleton模式)的精神。

另一件可以做的事情是防止你的类被继承,因为派生类将无法访问你的类构造函数。当然,在这种情况下,你仍需要一个创建类实例的函数。


1
不确定,但拥有复制构造函数会很好。不过由于RVO的原因,我不太确定。 - Pawel Zubrycki
3
@Pawel - C++ FAQ 中的例子没有为 Point 定义复制构造函数,因为该类只有原始成员(两个 float),所以编译器的默认复制构造函数(执行浅拷贝)就足够使用在这个例子中。 - wkl
1
终于有一个不是单例或工厂的例子了。命名构造函数似乎更有用。 - chrisaycock
2
我刚刚看到了你的这句话:“...返回的Point表示哪个坐标系”。无论使用哪种构造函数创建对象,Point本身始终使用直角坐标(否则,在我看来,这将是一个糟糕的例子)。我查看了常见问题解答,并且认为那里的表述也可能会误导:“...在任一坐标系中创建点:”。我认为最好应该这样说:“通过提供参数以任一坐标系的形式创建具有直角坐标的点。”我可能听起来很挑剔,但对于像我这样的新手来说,这些细节可以产生巨大的差异。 - 463035818_is_not_a_number

33

单例模式中常用到的技术之一是只允许类的一个实例存在。为了实现这个目标,可以提供一个static方法来创建对象的实例。通过这种方式,可以控制特定类的实例化数量。


22
每次我提到单例作为一种特定成语的用例时,总是会被踩。希望你不要遭遇同样的情况! :) - Moo-Juice

6

私有构造函数在您不希望用户实例化类时非常有用。要实例化这样的类,您需要声明一个静态方法,执行'new'并返回指针。

具有私有构造函数的类不能放入STL容器中,因为它们需要复制构造函数。


5

如果有其他方法可以产生实例,则将构造函数设置为私有是合理的。明显的例子是Singleton模式(每次调用返回相同的实例)和Factory模式(每次调用通常会创建新实例)。


2

当您想要实现单例模式时,这是很常见的。该类可以有一个静态的“工厂方法”,检查类是否已经被实例化,并在没有实例化时调用构造函数。


1

一个常见的用途是用于模板typedef解决类,如下所示:

template <class TObj>
class MyLibrariesSmartPointer
{
  MyLibrariesSmartPointer();
  public:
    typedef smart_ptr<TObj> type;
};

显然,一个公共的未实现的构造函数也可以工作,但是一个私有的构造函数会在编译时而不是链接时引发错误,如果有人尝试实例化MyLibrariesSmartPointer<SomeType>而不是MyLibrariesSmartPointer<SomeType>::type,这是可取的。


1
例如,您可以在友元类或友元函数中调用私有构造函数。 单例模式通常使用它来确保没有人创建更多预期类型的实例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接