问题描述
class A{public: int id; static A getA() {return self; }private: static A self; A(){id = 3;std::cout << 'A' << ' '; }};
代码如上, 类似这样的类, 我要如何初始化self呢?
同时我发现, 我如果这样写的话, 它会默认调用可以初始化A()初始化self, 屏幕上能显示 A第一行3, 但是如果我在头文件中倒数第二行 A::self 改成 A::self(); 就报错, 说我重定义了self, 他说之前self是一个属性, 这里我重定义它为一个函数...
#include <iostream>#include 'A.h'using namespace std;int main(void){ cout << '第一行'; cout << A::self.x;}#ifndef LAB_A_H#define LAB_A_H#include <iostream>class A{public: int x = 3; static A self;private: A(){std::cout << 'A'; }};A A::self;#endif //LAB_A_H
问题在于 :
对于这种成员的初始化, 如果使用默认的构造函数就不能加括号是吗?(我尝试过用一个带参数的构造函数, 是可以编译运行的)
如果我去掉最后一行, 也就是不对这个静态属性self进行初始化, 只要我main.cpp中不用到这个类, 我就算include这个头文件(显然是错误的), 也可以正常运行, 这又是为什么呢?
问题解答
回答1:如果这个类你能改,那么标准做法是
static A& getA() { static A a; return a;}
a只会被初始化一次,在第一次getA被调用时.自C++11以后这个是线程安全的.
如果你不能改,那么你只能在类外初始化这个self。 而你的构造函数是私有的,然后就初始化不了了.
对于你的默认构造函数不带()问题: 对的,带括号会引起歧义,编译器会理解成这是一个函数签名
A a(); // 声明一个返回值为A,不含参数的函数回答2:
在a.cpp里面这样写即可:
// a.cpp#include 'a.h'A A::self;
测试了一下:
// main.cpp#include 'a.h'int main() { A a = A::getA(); std::cout << '| static A.id:' << a.id << std::endl; return 0;}// output:A | static A.id:3