今天在看两种单例模式的时候有一点疑惑查了点资料,记录一下
懒汉模式
class Singleton
{
private:
static Singleton* instance;
private:
Singleton() {}
Singleton(const Singleton&); //这是一个函数声明,函数定义的时候需要给具体参数名
public:
static Singleton* getInstance()
{
if (instance == nullptr)
instance = new Singleton();
return instance;
}
};
Singleton* Singleton::instance = nullptr;
饿汉模式
class Singleton
{
public:
static Singleton* getInstance()
{
return instance_;
}
private:
Singleton() {}
Singleton(const Singleton&);
static Singleton* instance_;
};
Singleton* Singleton::instance_ = new Singleton();
在看这个单例模式的时候出现了一个问题
静态私有成员变量是否受到private的私有限制
先说结果:受到private的限制,即使是static加上私有限制也不能从类外访问
在C++中,静态成员变量是属于类的,而不是属于类的任何特定对象的。这意味着,无论你创建了多少个类的对象,静态成员变量只有一个副本。静态成员变量在所有对象之间共享,它们在类外部初始化。
私有静态成员变量的初始化是一个特例。尽管它们是私有的,但是它们可以在类外部初始化。这是因为静态成员变量的初始化不是通过访问控制进行的,而是在编译时进行的。在编译时,编译器知道静态成员变量的类型和大小,因此可以为它们分配内存和初始化。
class MyClass {
private:
static int myPrivateStaticVar;
public:
void myFunction() {
myPrivateStaticVar = 10; // 这是合法的,因为myFunction是MyClass的成员函数
}
};
int MyClass::myPrivateStaticVar = 0; // 这是合法的,因为静态成员变量在类外部初始化
在这个例子中,myPrivateStaticVar
是MyClass
的私有静态成员变量。尽管它是私有的,但是它可以在类外部初始化。这是因为静态成员变量的初始化在编译时进行,而不是在运行时进行。
然而,尽管你可以在类外部初始化私有静态成员变量,但是你不能在类外部访问它。如果你试图在类外部访问私有静态成员变量,编译器将会报错。
在全局使用作用域的时候编辑器提示可以使用私有变量的问题
在C++中,私有成员(包括变量和函数)只能在类的内部访问,这是封装的一个重要方面。私有成员的访问权限是受限的,只有类的成员函数和友元函数可以访问。
当你在全局范围内使用类的作用域时,编辑器可能会提示你可以使用私有变量,这是因为编辑器在提供代码提示时,会考虑到所有可能的代码片段,包括私有成员。然而,这并不意味着你可以在全局范围内访问私有成员。如果你尝试这样做,编译器将会报错。
int Singleton::a = 1; //编辑器报错,非静态数据成员不能在类外定义
当你在函数内部使用类的作用域时,你已经离开了类的作用域,进入了函数的作用域。在函数的作用域内,你不能访问类的私有成员,包括私有变量。因此,编辑器在提供代码提示时,不会提示私有变量。
class MyClass {
private:
int myPrivateVar;
};
void myFunction() {
int var = MyClass::myPrivateVar; // 这将导致编译错误,因为myPrivateVar是私有的
}
为什么调用私有构造函数没有报错
代码是上述单例模式饿汉模式中的
Singleton* Singleton::instance_ = new Singleton();
Singleton* a = new Singleton();
上述两端代码第一个编辑器不报错,第二个编辑器报错
Singleton* Singleton::instance_ = new Singleton();
这行代码是在类的内部初始化静态成员变量instance_。尽管构造函数是私有的,但是类的静态成员可以访问类的所有成员,包括私有成员。因此,这行代码是合法的,不会导致编译错误。
Singleton* a = new Singleton();
这行代码试图在类的外部创建一个新的Singleton实例。因为Singleton的构造函数是私有的,所以这是不允许的,会导致编译错误