在C++的类设计中,构造函数通常用于创建类的实例,而将构造函数设置为私有可以限制类的实例化方式,这种设计在单例模式、静态工厂模式等场景中非常实用。私有构造函数只能被类自身的静态成员函数或者友元访问,外部无法直接通过new或者栈上创建对象。

私有构造函数的基础实现
要将构造函数设置为私有,只需要在类的private访问权限下声明构造函数即可,示例代码如下:
#include <iostream>
class PrivateConstructDemo {
private:
// 私有构造函数,外部无法直接调用
PrivateConstructDemo() {
std::cout << "私有构造函数被调用" << std::endl;
}
public:
// 静态成员函数,可以访问私有构造函数
static PrivateConstructDemo* createInstance() {
return new PrivateConstructDemo();
}
};
int main() {
// PrivateConstructDemo obj1; // 编译错误,无法访问私有构造函数
// PrivateConstructDemo* obj2 = new PrivateConstructDemo(); // 编译错误
PrivateConstructDemo* obj3 = PrivateConstructDemo::createInstance(); // 正确,通过静态函数创建
delete obj3;
return 0;
}
私有构造函数在单例模式中的用法
单例模式要求一个类只能有一个实例,并且提供全局访问点,私有构造函数是阻止外部创建多实例的核心手段。单例模式通常有两种实现方式:饿汉式和懒汉式。
饿汉式单例实现
饿汉式在程序启动时就创建唯一的实例,线程安全,实现如下:
#include <iostream>
class HungrySingleton {
private:
// 私有构造函数,阻止外部实例化
HungrySingleton() {
std::cout << "饿汉式单例构造函数调用" << std::endl;
}
// 静态实例,程序启动时初始化
static HungrySingleton* instance;
public:
// 获取唯一实例的静态方法
static HungrySingleton* getInstance() {
return instance;
}
void doSomething() {
std::cout << "饿汉式单例执行操作" << std::endl;
}
};
// 初始化静态成员
HungrySingleton* HungrySingleton::instance = new HungrySingleton();
int main() {
HungrySingleton* s1 = HungrySingleton::getInstance();
HungrySingleton* s2 = HungrySingleton::getInstance();
s1->doSomething();
// 验证两个指针指向同一个实例
std::cout << "s1地址: " << s1 << std::endl;
std::cout << "s2地址: " << s2 << std::endl;
return 0;
}
懒汉式单例实现(线程安全版)
懒汉式在第一次调用时才创建实例,需要加锁保证线程安全,避免多线程下创建多个实例:
#include <iostream>
#include <mutex>
class LazySingleton {
private:
// 私有构造函数
LazySingleton() {
std::cout << "懒汉式单例构造函数调用" << std::endl;
}
static LazySingleton* instance;
static std::mutex mtx; // 互斥锁保证线程安全
public:
static LazySingleton* getInstance() {
if (instance == nullptr) { // 双重检查,减少锁的开销
std::lock_guard<std::mutex> lock(mtx);
if (instance == nullptr) {
instance = new LazySingleton();
}
}
return instance;
}
void doSomething() {
std::cout << "懒汉式单例执行操作" << std::endl;
}
};
// 初始化静态成员
LazySingleton* LazySingleton::instance = nullptr;
std::mutex LazySingleton::mtx;
int main() {
LazySingleton* s1 = LazySingleton::getInstance();
LazySingleton* s2 = LazySingleton::getInstance();
s1->doSomething();
std::cout << "s1地址: " << s1 << std::endl;
std::cout << "s2地址: " << s2 << std::endl;
return 0;
}
私有构造函数在静态工厂模式中的用法
静态工厂模式通过一个静态方法统一创建类的实例,私有构造函数可以隐藏类的构造细节,让创建逻辑完全由工厂方法管控,还可以根据参数返回不同的子类实例。以下是一个简单的静态工厂示例:
#include <iostream>
#include <string>
// 产品基类
class Product {
protected:
Product() {} // 基类构造函数设为protected,允许子类访问
public:
virtual void use() = 0;
virtual ~Product() {}
};
// 具体产品A
class ProductA : public Product {
private:
ProductA() {} // 私有构造函数,只有工厂可以创建
friend class ProductFactory; // 声明工厂为友元,允许工厂访问私有构造函数
public:
void use() override {
std::cout << "使用产品A" << std::endl;
}
};
// 具体产品B
class ProductB : public Product {
private:
ProductB() {}
friend class ProductFactory;
public:
void use() override {
std::cout << "使用产品B" << std::endl;
}
};
// 静态工厂类
class ProductFactory {
public:
// 静态工厂方法,根据类型创建产品
static Product* createProduct(const std::string& type) {
if (type == "A") {
return new ProductA();
} else if (type == "B") {
return new ProductB();
}
return nullptr;
}
};
int main() {
Product* p1 = ProductFactory::createProduct("A");
Product* p2 = ProductFactory::createProduct("B");
if (p1) {
p1->use();
delete p1;
}
if (p2) {
p2->use();
delete p2;
}
return 0;
}
使用注意事项
- 私有构造函数会阻止编译器自动生成默认构造函数,如果需要无参构造之外的其他构造函数,也需要显式声明为私有。
- 单例模式中如果需要释放实例,要额外设计销毁方法,避免内存泄漏。
- 静态工厂模式中如果需要创建子类实例,通常需要将子类的构造函数设为私有,并声明工厂为友元类。
通过合理设置私有构造函数,可以让类的实例化逻辑更加可控,符合设计模式的要求,提升代码的可维护性和扩展性。