类中,若将一个成员变量声明为static,这种成员称为静态成员变量。无论建立多少对象,都只有一个静态数据的拷贝。静态成员变量属于某个类,所有对象共享。
#include
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
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
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
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结果是1,因为每个实例对象,都有独一无二的地址,char维护这个地址。
静态成员函数里面没有this指针,非静态成员函数里面才有this指针。
下面代码中,可以通过一个类类型的空指针来调用类的成员函数吗?
#include
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
#include
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();
void test() const{
}
成员函数后面加了const,这this指针从 int * const p转成了const int * const p .
常函数中的参数也可以修改 mutiable
const Person p;
常对象不能调用普通成员函数,可以调用常函数。