静态成员变量
类中,若将一个成员变量声明为static,这种成员称为静态成员变量。无论建立多少对象,都只有一个静态数据的拷贝。静态成员变量属于某个类,所有对象共享。
- 静态变量,是在编译阶段就分配空间,对象还没有创建时,就已经分配空间。
- 静态成员变量必须在类中声明,在类外定义。
- 静态数据成员不属于某个对象,在为对象分配空间中不包括静态成员所占空间。
- 静态数据成员可以通过类名或者对象名来引用。
#include <iostream>
using namespace std;
class Test {
public:
static int p;
};
int Test::p = 10;//初始化静态变量
int main() {
cout << Test::p << endl;
Test t1;
t1.p = 20;
cout << t1.p << endl;
Test t2;
t1.p = 30;
cout << t2.p << endl;
return 0;
}
类的所有对象共享,因此谁都可以改。
静态成员函数——对象共享
静态成员函数不可以访问普通的成员变量,可以访问静态成员变量。
普通成员函数可以访问普通成员变量,也可以访问静态成员变量。
静态成员函数里面没有this指针,非静态成员函数里面才有this指针。
单例模式
单例模式例子
将构造函数设置成private之后,声明一个静态成员变量指针,外界可以通过指针来获取我们的对象。
但是外界也可以通过指针把我们的对象给销毁,如下:
#include <iostream>
using namespace std;
class Test {
public:
static Test *tt;
private:
Test() {}
};
//创建对象
Test * Test::tt=new Test;
void test() {
/*Test t1;
Test *t2 = new Test;*/
//获取指向Test类对象的指针
//构造函数生命为private之后,上面的两种方法便不能再创建对象了,
//因为构造函数无法访问了
Test* user1=Test::tt;
Test* user2 = Test::tt;
//我们创建的对象被清空了
Test::tt = NULL;
}
因此需要把静态成员变量指针也设置为空。如果这样,那么我们该如何访问这个指针呢?此时我们需要写一个静态成员函数作为接口,使得外界可以获取我们的对象。但是,外界可以通过拷贝构造函数来创建对象。
#include <iostream>
using namespace std;
class Test {
public:
static Test*getInstance() {
return tt;
}
private:
static Test *tt;
Test() {}
};
//创建对象
Test * Test::tt=new Test;
void test() {
Test *user1 = Test::getInstance();
Test *user2 = Test::getInstance();
if (user1 == user2) {
cout << "相同" << endl;
}
//通过拷贝构造函数,依然可以创建对象
Test* user3 = new Test(*user2);
if (user3 != user2) {
cout << "user2和user3不相同" << endl;
}
}
int main() {
test();
return 0;
}
因此,拷贝构造也要放在private里面。
#include <iostream>
using namespace std;
class Test {
public:
static Test*getInstance() {
return tt;
}
private:
static Test *tt;
Test() {}
Test(const Test&test){}
};
//创建对象
Test * Test::tt=new Test;
void test() {
Test *user1 = Test::getInstance();
Test *user2 = Test::getInstance();
if (user1 == user2) {
cout << "相同" << endl;
}
}
int main() {
test();
return 0;
}
总结:
目的——是我们的类只有一个实例,实例不需要自己释放。
要把构造函数,拷贝构造函数和指向对象的静态指针都设置成private,对外只提供一个结构来获取变量。
空类的sizeof结果
空类的sizeof结果是1,因为每个实例对象,都有独一无二的地址,char维护这个地址。
类中什么属于对象?
- 非静态成员变量,属于对象
- 非静态成员函数,不属于对象
- 静态成员变量,不属于对象
- 静态成员函数,不属于对象
this指针
静态成员函数里面没有this指针,非静态成员函数里面才有this指针。
下面代码中,可以通过一个类类型的空指针来调用类的成员函数吗?
#include <iostream>
using namespace std;
class Test {
public:
void test1() {
cout << "test1" << endl;
}
void test2() {
cout << age << endl;
}
private:
int age;
};
int main() {
Test *t = NULL;
//可以调用
t->test1();
//不可以
t->test2();
return 0;
}
因为成员函数有this指针,因此上面的代码执行时期其实是这样的:
class Test {
public:
void test1(Test *const this) {
cout << "test1" << endl;
}
void test2(Test *const this) {
cout << this->age << endl;
}
private:
int age;
};
因此test2是通过一个指向NULL的this指针来获取age,因此会崩溃。
成员函数可以通过添加对this指针的判空来提高程序的安全性
void test2() {
if (this == NULL) {
return;
}
cout << this->age << endl;
}
友元相关
友元函数
可以访问类内的私有属性
例子
#include <iostream>
#include<string>
using namespace std;
class Test {
public:
Test(int a = 10) :age(a) {}
string name;
private:
friend void goodGay(Test &t);
int age;
};
void goodGay(Test &t) {
cout << t.name << endl;
cout << t.age << endl;
}
int main() {
Test t;
t.name = "老王";
goodGay(t);
return 0;
}
友元类
在类中声明如下即可。
friend class 类名;
友元类是单向不可传递的。
成员函数作为友元函数
friend void goodGay::visit2();
const
常函数——函数后面是const
void test() const{
}
成员函数后面加了const,这this指针从 int * const p转成了const int * const p .
常函数中的参数也可以修改 mutiable
常对象——不允许修改内部属性
const Person p;
常对象不能调用普通成员函数,可以调用常函数。