1.概要
起因:很多时候类都是需要单件的,可以用静态的方式类解决。但用单件有些情况效果更到。
我起初想用静态构造函数来做静态成员的初始化,但是没有成功,所以使用了这个例子。
其实理想的方式是在静态构造函数内对静态成员初始化。
2.代码
#include <iostream>
#include "A.h"
int main()
{
int b = A::getMy()->fun(5);
std::cout << b<<"\n";
std::cout << "Hello World!\n";
}
#pragma once
class A
{
public:
int fun(int a);
static A* myF;
static int a;
static A* getMy();
};
#include "A.h"
int A::a = 1;
A* A::myF = 0;
int A::fun(int a) {
return a * a;
}
A* A::getMy() {
if (myF == 0) {
myF = new A();
}
return myF;
}
3.运行结果
4.补充说明
4.1 c++ 静态成员变量
在C++中,静态成员变量(也称为类变量或静态类成员)是类的所有实例(对象)共享的变量。这意味着无论创建了多少个类的对象,都只有一个静态成员变量的副本。静态成员变量在类的所有实例之间都是相同的,并且在类的作用域内是可访问的。
静态成员变量的一些特点:
- 静态存储期:静态成员变量具有静态存储期,这意味着它们的生命周期与整个程序相同。
- 类作用域:静态成员变量属于类,而不属于类的任何对象。因此,它们可以通过类名和作用域解析运算符(
::
)来访问,而无需创建类的对象。 - 初始化:静态成员变量必须在类外部进行初始化,并且只能初始化一次。
下面是一个示例,展示了如何在C++中定义和使用静态成员变量:
#include <iostream>
class MyClass {
public:
// 声明静态成员变量
static int count;
// 构造函数,每次创建对象时增加计数
MyClass() {
count++;
}
// 静态成员函数,用于访问静态成员变量
static void printCount() {
std::cout << "Objects created: " << count << std::endl;
}
};
// 在类外部初始化静态成员变量
int MyClass::count = 0;
int main() {
MyClass obj1; // count 现在为 1
MyClass::printCount(); // 输出 "Objects created: 1"
MyClass obj2; // count 现在为 2
MyClass::printCount(); // 输出 "Objects created: 2"
return 0;
}
在上面的示例中,我们定义了一个名为MyClass
的类,该类具有一个静态成员变量count
和一个静态成员函数printCount()
。我们在类外部初始化了静态成员变量count
,并在构造函数中每次创建对象时增加其值。我们还使用静态成员函数来访问静态成员变量并打印其值。
4.2 c++ 静态类成员
在C++中,静态类成员(包括静态成员变量和静态成员函数)是与类关联但与类的任何特定对象实例无关的成员。静态类成员在类的所有实例之间共享,并且可以通过类名和作用域解析运算符::
来访问,而不需要类的实例。
静态成员变量
静态成员变量在类的所有实例之间共享其值。静态成员变量在类的定义之外进行定义和初始化。下面是一个示例:
#include <iostream>
class MyClass {
public:
// 声明静态成员变量
static int count;
// 构造函数
MyClass() {
// 构造函数中更新静态成员变量
count++;
}
// 其他成员函数...
};
// 在类外部定义并初始化静态成员变量
int MyClass::count = 0;
int main() {
MyClass obj1; // count 现在为 1
MyClass obj2; // count 现在为 2
std::cout << "Objects created: " << MyClass::count << std::endl; // 输出 "Objects created: 2"
return 0;
}
静态成员函数
静态成员函数是类的成员函数,但它只能访问静态成员变量和其他静态成员函数。静态成员函数不能直接访问类的非静态成员变量或非静态成员函数,因为非静态成员是与类的特定实例关联的。
下面是一个示例,其中包含一个静态成员函数来访问静态成员变量:
#include <iostream>
class MyClass {
public:
// 声明静态成员变量
static int count;
// 声明静态成员函数
static void printCount() {
std::cout << "Objects created: " << count << std::endl;
}
// 构造函数
MyClass() {
count++;
}
// 其他成员函数...
};
// 在类外部定义并初始化静态成员变量
int MyClass::count = 0;
int main() {
MyClass obj1;
MyClass::printCount(); // 输出 "Objects created: 1"
MyClass obj2;
MyClass::printCount(); // 输出 "Objects created: 2"
return 0;
}
使用场景
静态类成员常用于以下场景:
- 需要跟踪类创建的对象数量时(如上述示例中的
count
)。 - 当一个函数只需要访问类的静态数据时(如工厂函数或工具函数)。
- 当一个函数只需要访问类的静态状态,而不需要访问或修改类的任何非静态成员时。
请注意,静态成员函数没有this
指针,因为它们不与类的特定实例关联。因此,静态成员函数不能访问或修改类的非静态成员(除非它们作为参数显式传递)。
4.3 c++ 静态成员变量是自定义类型
在C++中,静态成员变量也可以是自定义类型(即类类型或结构体类型)。当静态成员变量是自定义类型时,你需要在类外部为其分配内存并构造(如果需要的话)。这通常涉及到使用类的构造函数来初始化静态成员变量。但是,对于静态成员变量,你不能直接在类定义中调用构造函数,因为静态成员变量不属于任何类的特定实例。
然而,你可以使用一种称为“局部静态变量初始化”的技巧来在第一次访问静态成员变量时为其分配内存和构造。这种方法利用了C++中局部静态变量在首次进入其定义的作用域时初始化的特性。
以下是一个示例,展示了如何在C++中使用自定义类型的静态成员变量:
#include <iostream>
class MyCustomType {
public:
int value;
MyCustomType(int v) : value(v) {}
void printValue() const {
std::cout << "Value: " << value << std::endl;
}
};
class MyClass {
public:
// 声明静态成员变量,类型为MyCustomType
static MyCustomType staticMember;
// 静态成员函数,用于访问静态成员变量
static void printStaticMember() {
staticMember.printValue();
}
// 注意:我们不在类定义中初始化staticMember
};
// 在类外部定义并初始化静态成员变量
// 注意这里我们使用了一个匿名命名空间来确保只初始化一次
namespace {
MyCustomType& initStaticMember() {
static MyCustomType instance(42); // 初始化静态成员变量
return instance;
}
}
// 使用函数初始化的技巧来初始化静态成员变量
MyCustomType& MyClass::staticMember = initStaticMember();
int main() {
MyClass::printStaticMember(); // 输出 "Value: 42"
return 0;
}
在上面的示例中,我们使用了一个匿名命名空间中的initStaticMember
函数来初始化MyClass::staticMember
。这个函数返回一个对局部静态变量instance
的引用,该变量在第一次调用initStaticMember
时被构造。由于initStaticMember
函数只在MyClass::staticMember
的定义中被调用一次,因此instance
也只会被构造一次。
这种方法的优点是它允许你在类外部控制静态成员变量的初始化,并且可以处理更复杂的初始化逻辑(例如,可能需要调用其他函数或进行条件检查)。然而,它也增加了代码的复杂性,因此应该谨慎使用。在大多数情况下,如果静态成员变量的初始化很简单,直接在类外部进行初始化就足够了。