静态成员
静态成员变量
所有对象都共享同一份数据
编译阶段就分配内存
类内声明、类外初始化
访问方式有两种:通过对象访问、通过类名访问
静态成员变量也是有访问权限,私有权限类外访问不到
静态成员函数
所有对象都共享同一份函数
静态成员函数 只可以访问 静态成员变量,不可以访问非静态成员变量
静态成员函数 也是有访问权限的
静态成员函数 有两种访问方式:通过对象 、通过类名
示例
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//1. 静态成员变量
class Person
{
public:
//静态成员变量:编译阶段就分配了内存
//类内声明、类外初始化
//静态成员变量,所有对象都共享同一份数据
static int m_A;
int m_C;
//2. 静态成员函数
//所有对象都共享同一个func函数
static void func()
{
m_A = 100; //静态成员函数只能修改静态成员变量
// m_C = 100; 报错,非静态成员变量不可以访问,因为无法区分到底要修改哪个对象
cout << "func的调用" << endl;
}
private:
static int m_B; //私有的静态成员变量,有访问权限,私有权限类外访问不到
static void func2();
};
int Person::m_A = 0; //要写作用域
void test01()
{
//1. 通过对象进行访问
Person p1;
cout << p1.m_A << endl;
Person p2;
p2.m_A = 100;
cout << p1.m_A << endl;
//2. 通过类名进行访问
cout << Person::m_A << endl;
//静态成员变量也是有访问权限的,私有权限类外访问不到
//cout <<Person :: m_B << endl; 访问不到,因为是私有权限
}
//静态成员函数两种调用方式
void test02()
{
//通过对象
Person p1;
p1.func();
//通过类名
Person::func();
//Person::func2(); 无法调用,也是访问权限的
}
int main()
{
test01();
test02();
system("pause");
return EXIT_SUCCESS;
}
单例模式
单例模式 – 主席类案例
通过一个类 只能实例化唯一的一个对象
-
私有化
默认构造
拷贝构造
-
唯一实例指针
-
对外提供 getInstance 接口,将指针返回
示例:主席类
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//主席类
class ChairMan
{
public:
static ChairMan* getInstance()
{
return singleMan;
}
private:
//将构造函数私有化,不可以创建多个对象
ChairMan()
{
};
ChairMan(const ChairMan&) //解决可以通过拷贝建立新的对象的过程
{
}
//public:
private:
//将主席指针私有化,对外提供只读接口
static ChairMan* singleMan;//类内声明,类外初始化
};
ChairMan* ChairMan::singleMan = new ChairMan;
void test01()
{
//ChairMan* c1 = ChairMan::singleMan;
//ChairMan* c2 = ChairMan::singleMan;
ChairMan* c1 = ChairMan::getInstance();
ChairMan* c2 = ChairMan::getInstance();
//ChairMan* c3 = new ChairMan(*c1);
if (c1 == c2)
{
cout << "c1=c2" << endl;
}
else
{
cout << "c1 != c2" << endl;
}
if (c1 == c3)
{
cout << "c1=c3" << endl;
}
else
{
cout << "c1 != c3" << endl;
}
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
单例模式 – 打印机案例
和主席类案例一样设计单例模式
提供打印功能并且统计打印次数
示例
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
class Printer
{
public:
static Printer* getInstance()
{
return printer;
}
void printText(string text)
{
m_Count++;
cout << text << endl;
}
int m_Count;
private:
//编译阶段就分配内存,可以通过这种方法在main函数调用之前打印
Printer()
{
m_Count = 0;
cout << "打印机的构造调用" << endl;
}
Printer(const Printer& p)
{
}
static Printer* printer;
};
Printer* Printer::printer = new Printer;
void test01()
{
Printer* p1 = Printer::getInstance();
p1->printText("入职证明");
p1->printText("离职证明");
p1->printText("加薪申请");
p1->printText("旅行申请");
cout << "打印机使用次数" << p1->m_Count << endl;
Printer* p2 = Printer::getInstance();
p2->printText("调休申请");
cout << "打印机使用次数" << p2->m_Count << endl;
}
int main()
{
cout << "main函数调用" << endl;
test01();
system("pause");
return EXIT_SUCCESS;
}
C++对象模型初探
类中的成员变量 和 成员函数 是分开存储的
只有非静态成员变量 属于类对象上
空类的sizeof结果 1
示例
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
int m_A; //只有非静态成员变量 属于类对象上
void func() //成员函数 并不属于类对象上
{
}
static int m_B;//静态成员变量 不属于类对象上
static void func2() //静态成员函数 不属于类对象上
{
}
double m_C; //以8位模数对齐
};
int Person::m_B = 0;
void test01()
{
//空类的sizeof结果是1,原因 每个对象都应该在内存上有独一无二的地址,因此给空对象分配1个字节空间
Person p1;
cout << "sizeof = " << sizeof(p1) << endl;
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
this指针
this指针 指向 被调用的成员函数 所属的对象
-
this指针可以解决名称冲突
-
this指针 隐式加在每个成员函数中
-
*this 就是本体
p1.personAddPerson(p2).personAddPerson(p2).personAddPerson(p2); //链式编程
示例
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person(int age)
{
// 用途1 解决名称冲突
this->age = age;
}
//this 指针 隐式加在每个成员函数中
bool cmpareAge(Person & p)
{
if (this->age == p.age)
{
return true;
}
return false;
}
Person& persnAddPerson(Person& p)
{
this->age += p.age;
return *this;//用引用的方式返回本身,可以多次复用链式编程
}
int age;
};
void test01()
{
//this 指针 指向被调用的成员函数所属的对象
Person p1(18);
cout << "p1 age " << p1.age << endl;
Person p2(18);
bool ret = p1.cmpareAge(p2);
if (ret)
{
cout << "p1 == p2" << endl;
}
//上面的函数如果不是返回引用改为返回值,则只有第一次调用是p1,后面调用的是拷贝构造函数生成的p1拷贝,不是p1本身
p1.persnAddPerson(p2).persnAddPerson(p2).persnAddPerson(p2); //链式编程
cout << "age of p1:" << p1.age << endl;
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
空指针访问成员函数
-
如果成员函数中没有用到this指针,可以用空指针调用成员函数
-
如果成员函数中用到了this,那么这个this需要加判断,防止代码down掉
示例
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
void showClass()
{
cout << "class Name is Person" << endl;
}
void showAge()
{
if (this == NULL) //防止别人用空指针调用成员函数代码崩掉
{
return;
}
m_Age = 0;
cout << "age = " << this->m_Age << endl;
}
int m_Age;
};
void test01()
{
Person* p = NULL;
p->showClass();
p->showAge();
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
常对象和常函数
常函数
成员函数 声明后面加const
void showPerson() const
const目的是为了修饰成员函数中的this指针,让指针指向的值不可以修改
有些属性比较特殊,依然在常函数或者常对象中可以修改,需要加入关键字 mutable
常对象
const Person p
常对象也不许修改成员属性
常对象只能调用常函数
对于成员函数 ,不可以 用static 和 const同时修饰
友元
程序员可以把一个全局函数、某个类中的成员函数、甚至整个类声明为友元。
全局函数作为友元函数
利用friend关键字让全局函数 goodGay作为本类好朋友,可以访问私有成员
friend void goodGay(Building * buliding);
示例
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<string>
class Building
{
//利用friend关键字让全局函数 goodGay作为本类友元 可以访问私有属性
friend void goodGay(Building* building);
public:
Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
}
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom;//卧室
};
//好基友 全局函数 可以访问 Building的私有属性
void goodGay(Building* building)
{
cout << "好基友正在访问" << building->m_SittingRoom << endl;
cout << "好基友正在访问" << building->m_BedRoom << endl;
}
void test01()
{
Building building;
goodGay(&building);
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
类作为友元类
让goodGay类作为 Building的好朋友,可以访问私有成员
friend class GoodGay;
示例:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include <string>
class Building;
class goodGay
{
public:
goodGay();
void visit();
Building* m_building;
};
class Building
{
//让goodGay类作为Building的好朋友可以访问私有成员
friend class goodGay;
public:
Building();
string m_SittingRoom;
private:
string m_BedRoom;
};
//Building构造函数的类外实现
Building::Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
}
goodGay::goodGay()
{
this->m_building = new Building;
}
void goodGay::visit()
{
cout << "好基友正在访问:" << this->m_building->m_SittingRoom << endl;
cout << "好基友正在访问:" << this->m_building->m_BedRoom << endl;
}
void test01()
{
goodGay gg;
gg.visit();
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
类中的成员函数作为友元函数
让GoodGay类中的 visit成员函数作为友元
friend void GoodGay::visit();
示例
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include <string>
class Building;
class goodGay
{
public:
goodGay();
void visit(); //可以访问Building的私有
void visit2(); //不可以访问Building的私有
Building* m_building;
};
class Building
{
//让goodGay中的visit成员函数作为友元
friend void goodGay::visit();
public:
Building();
string m_SittingRoom;
private:
string m_BedRoom;
};
//Building构造函数的类外实现
Building::Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
}
goodGay::goodGay()
{
this->m_building = new Building;
}
void goodGay::visit()
{
cout << "好基友正在访问:" << this->m_building->m_SittingRoom << endl;
cout << "好基友正在访问:" << this->m_building->m_BedRoom << endl;
}
void goodGay::visit2()
{
cout << "好基友正在访问:" << this->m_building->m_SittingRoom << endl;
cout << "好基友正在访问:" << this->m_building->m_BedRoom << endl; //报错
}
void test01()
{
goodGay gg;
gg.visit2();
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}