c++基础梳理 2019.1.14(静态成员变量,静态成员函数,单例模式,空类的sizeof结果,this指针,友元函数,友元类,成员函数作为友元函数,常函数,常对象)

静态成员变量

类中,若将一个成员变量声明为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结果

空类的sizeof结果是1,因为每个实例对象,都有独一无二的地址,char维护这个地址。

 

 

类中什么属于对象?

  • 非静态成员变量,属于对象
  • 非静态成员函数,不属于对象
  • 静态成员变量,属于对象
  • 静态成员函数,属于对象

 

 

 

this指针

静态成员函数里面没有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();

 

 

const

常函数——函数后面是const

void test() const{

}

成员函数后面加了const,这this指针从 int * const p转成了const int * const p .

 

常函数中的参数也可以修改    mutiable

c++基础梳理 2019.1.14(静态成员变量,静态成员函数,单例模式,空类的sizeof结果,this指针,友元函数,友元类,成员函数作为友元函数,常函数,常对象)_第1张图片

 

常对象——不允许修改内部属性

const Person p;

常对象不能调用普通成员函数,可以调用常函数。

c++基础梳理 2019.1.14(静态成员变量,静态成员函数,单例模式,空类的sizeof结果,this指针,友元函数,友元类,成员函数作为友元函数,常函数,常对象)_第2张图片

你可能感兴趣的:(C++基础)