我有一个关于 C++ 中私有构造函数的问题。如果构造函数是私有的,我如何创建该类的实例?
我们应该在类中拥有 getInstance() 方法吗?
有一些场景需要使用
private
构造函数:
限制除
friend
之外的所有对象的对象创建;在这种情况下,所有构造函数都必须是 private
class A
{
private:
A () {}
public:
// other accessible methods
friend class B;
};
class B
{
public:
A* Create_A () { return new A; } // creation rights only with `B`
};
限制某些类型的构造函数(即复制构造函数、默认构造函数)。例如
std::fstream
不允许通过这种不可访问的构造函数进行复制
class A
{
public:
A();
A(int);
private:
A(const A&); // C++03: Even `friend`s can't use this
A(const A&) = delete; // C++11: making `private` doesn't matter
};
拥有一个通用的委托构造函数,该构造函数不应该暴露给外部世界:
class A
{
private:
int x_;
A (const int x) : x_(x) {} // common delegate; but within limits of `A`
public:
A (const B& b) : A(b.x_) {}
A (const C& c) : A(c.foo()) {}
};
对于 单例模式,当单例
class
不可继承时(如果可继承,则使用 protected
构造函数)
class Singleton
{
public:
static Singleton& getInstance() {
Singleton object; // lazy initialization or use `new` & null-check
return object;
}
private:
Singleton() {} // make `protected` for further inheritance
Singleton(const Singleton&); // inaccessible
Singleton& operator=(const Singleton&); // inaccessible
};
私有构造函数通常与 Builder 方法一起使用,例如在 Named Constructor 习惯用法中。
class Point
{
public:
static Point Polar(double, double);
static Point Cartesian(double, double);
private:
Point(double,double);
};
在这个(典型)示例中,命名构造函数习惯用法用于明确使用哪个坐标系来构建
Point
对象。
当您想要控制类的对象创建时,私有构造函数非常有用。
让我们尝试一下代码:
#include <iostream>
using namespace std;
class aTestClass
{
aTestClass() ////////// Private constructor of this class
{
cout << "Object created\n";
}
public:
};
int main()
{
aTestClass a;
aTestClass *anObject;
}
行 aTestClass a 会导致错误,因为该行间接尝试访问私有构造函数。注释掉这一行并运行程序。它运行得非常好。现在的问题是如何在这种情况下创建对象。我们再写一个程序吧。
#include <iostream>
using namespace std;
class aTestClass
{
aTestClass() ////////// Private constructor of this class
{
cout << "Object created\n";
}
public:
aTestClass* getAnObject() ///// A public method create an object of this class and return the address of an object of that class
{
return (new aTestClass);
}
};
int main()
{
//aTestClass a;
aTestClass *anObject = NULL;
anObject = anObject->getAnObject();
}
输出是
Object created
因此我们创建了一个包含私有构造函数的类的对象。
使用这个概念来实现单例类
是的,这通常用在单例模式中,其中通过静态成员函数访问对象。
如果某个构造函数是私有的,则意味着除了类本身(和朋友)之外,没有人能够使用该构造函数创建它的实例。因此,您可以提供像 getInstance() 这样的静态方法来创建类的实例或在某些友元类/方法中创建实例。
这取决于为什么构造函数首先被设为私有(您应该询问编写您正在编辑的类的人)。有时,可以将构造函数设为私有以禁止复制构造(同时允许通过其他构造函数进行构造)。其他时候,构造函数可能会被设为私有,以禁止创建该类,除非该类的“朋友”(如果该类是“帮助器”,则通常会这样做,该类只能由该帮助器类所在的类使用)被创建)。构造函数也可以设为私有,以强制使用(通常是静态的)创建函数。
如果创建私有构造函数,则需要在类内创建对象
#include<iostream>
//factory method
using namespace std;
class Test
{
private:
Test(){
cout<<"Object created"<<endl;
}
public:
static Test* m1(){
Test *t = new Test();
return t;
}
void m2(){
cout<<"m2-Test"<<endl;
}
};
int main(){
Test *t = Test::m1();
t->m2();
return 0;
}
C++ 中的私有构造函数可用于限制常量结构的对象创建。你可以在相同的范围内定义类似的常量,如枚举:
struct MathConst{
static const uint8 ANG_180 = 180;
static const uint8 ANG_90 = 90;
private:
MathConst(); // Restricting object creation
};
像
MathConst::ANG_180
一样访问它。
我将它与返回
friend
的函数结合使用,以便安全地构造对象,同时避免异常。例如:std::optional
并像这样使用它:
#include <optional>
class Object {
private:
Object(...) { /* ... */ }
friend std::optional<Object> make_object(...);
};
std::optional<Object> make_object(...)
{
// ...
if (error)
return std::nullopt;
// else
return std::make_optional<Object>(...);
}