5. C++ 特殊成员
C++特殊成员
const成员
-
const修饰的数据成员
-
初始化必须采用初始化参数列表
-
不能被修改
-
构造函数必须要初始化常数据成员
-
-
const修饰的成员函数
-
写法上要注意: const修饰是写在函数后面
-
const成员函数不能修改任何的数据成员
-
如果实在是要在常成员函数中修改该数据,用mutable修饰数据成员即可
-
常成员函数可以普通函数同时存在
-
-
const对象
-
const修饰的对象
-
常对象只能调用常成员函数
-
#include <iostream>
using namespace std;
class MM
{
public:
MM(int age) :name("小芳"), num(4323)
{
this->age = age;
}
MM(string name, int age, int num) :name(name), age(age), num(num)
{
}
//MM() {} 常数据必须要初始化,错误
//MM() = default; //正确,可以构造无参对象
void print()
{
age = 18;
//num = 11; //不能修改常数据成员
cout << this->name << " " << this->num << " " << this->age << endl;
cout << "普通函数" << endl;
}
//常成员函数: const写在函数后面
void print() const
{
cout << this->name << " " << this->num << " " << this->age << endl;
cout << "常成员函数" << endl;
}
void printData() const
{
//age = 23; //常成员函数,不能修改数据成员
cout << this->name << this->num << this->age << endl;
}
void test() {}
protected:
//常数据成员
const string name;
const int num;
int age; //mutable 可修改的意思
};
int main()
{
MM mm("小丽", 18, 1001);
//如果普通函数和常成员函数同名
mm.print(); //普通对象优先调用普通函数
const MM object(18);
object.print(); //常对象只能调用常成员函数
object.printData();
//object.test(); //错误,常对象只能调用常成员函数
return 0;
}
static成员
static成员不属于某一个单独对象,是属于类的,通俗一点讲,是所有对象的共享的,static成员依然受权限
satic成员他的访问可以不需要对象(用类名限定的方式去访问)
-
static数据成员
-
初始化必须在类外初始化
-
类实现的时候不需要用static修饰了
-
-
static成员函数
-
static写在修饰函数的前面
-
类外实现也不需要static修饰
-
静态函数中没有this指针
-
静态成员函数的访问问题
-
静态成员函数访问静态成员 是可以直接访问
-
静态成员函数访问非静态数据成员,必须通过指定对象的方式
-
静态成员函数传参
-
在静态成员函数定义对象去访问
-
-
-
#include <iostream>
#include <string>
using namespace std;
class User
{
public:
User(string name = "默认")
{
this->count++; //类中访问
this->m_count++;
}
void print()
{
cout << name << " " << count << endl;
}
//void test() {} 不能和普通函数形参重载效果,会造成重定义问题
public:
static void test();
static void testData(User& object);
private:
string name;
public:
static int count;
int m_count = 0;
};
//必须在类外面做初始化,不需要static修饰了
int User::count = 0;
void User::test()
{
cout << "count:" << count << endl;
//cout << "m_count:" << m_count << endl; //静态成员函数中不能直接调用非静态成员
cout << "静态函数" << endl;
}
void User::testData(User& object)
{
cout << object.m_count << endl; //传参
User mm;
cout << mm.m_count << endl; //创建对象
}
int main()
{
cout << User::count << endl; //static 成员访问不需要对象
User object[3];
cout << User::count << endl;
User mm;
cout << mm.count << endl;
cout << User::count << endl; //可以用类名访问,前提是权限没问题
cout << mm.m_count << endl; //不能用类名
User::test(); //因为存在这种调用,所以静态成员函数中不能存在this指针
mm.test();
return 0;
}
单例设计模式
什么是设计模式
-
模式: 套路 —> 写代码的习惯
-
设计模式:前人总结的具有代表的套路 (官方说法:又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结)
-
设计模式究极目标: 通过增加代码的形式去减少因为变化而要修改原代码的问题(维护问题)
单例设计模式
什么是单例设计模式
保证整个类的使用只有一个对象
-
多线程网络资源初始化
-
回收站机制
-
任务管理器
-
日志管理
如何实现单例设计模式
-
构造函数私有化
-
提供一个全局的静态方法,访问唯一对象
-
类中定义一个而静态指针,指向唯一对象
单例设计模式实现代码
懒汉式
在类中创建一个对象(只有用的才去创建)
:线程不安全
/*
- 构造函数私有化
- 提供一个全局的静态方法,访问唯一对象
- 类中定义一个而静态指针,指向唯一对象
*/
#include <iostream>
using namespace std;
class SingleTon
{
public:
//类中定义一个而静态指针,指向唯一对象
static SingleTon* m_singleTon;
//提供一个全局的静态方法,访问唯一对象
static SingleTon* GetInstance()
{
if (m_singleTon == nullptr)
{
m_singleTon = new SingleTon;
}
return m_singleTon;
}
private:
SingleTon()
{
cout << "构造对象...." << endl;
m_singleTon = nullptr;
}
};
SingleTon* SingleTon::m_singleTon=nullptr;
int main()
{
SingleTon* p1 = SingleTon::GetInstance();
cout << "p1:" << p1 << endl;
SingleTon* p2 = SingleTon::GetInstance();
cout << "p2:" << p2 << endl;
return 0;
}
饿汉式
全局创建的一个对象(饥不择食,用不用都去创建)
:线程安全
/*
- 构造函数私有化
- 提供一个全局的静态方法,访问唯一对象
- 类中定义一个而静态指针,指向唯一对象
*/
#include <iostream>
using namespace std;
class SingleTon
{
public:
//类中定义一个而静态指针,指向唯一对象
static SingleTon* m_singleTon;
//提供一个全局的静态方法,访问唯一对象
static SingleTon* GetInstance()
{
return m_singleTon;
}
private:
SingleTon()
{
cout << "构造对象...." << endl;
}
};
SingleTon* SingleTon::m_singleTon=new SingleTon;
int main()
{
SingleTon* p1 = SingleTon::GetInstance();
cout << "p1:" << p1 << endl;
SingleTon* p2 = SingleTon::GetInstance();
cout << "p2:" << p2 << endl;
return 0;
}
单例设计优缺点
-
优点
-
内存中只有一个对象,节省内存空间
-
避免频繁创建和销毁对象,提高性能
-
避免对共享的资源的多重占用,简化访问
-
-
缺点
-
不适用变化频繁的对象
-
长时间不使用对象,导致系统回收掉
-
C++多文件写法
-
一个类一个模块
-
声明写在.h
-
实现写在.cpp
-
声明和试下写在一起 .hpp
-
头文件包含尽量在.cpp完成
-
设计项目时候,头文件形成交叉包含,说明思想有问题,自己重新设计代码
-
不要为了拆分而拆分
-
-
静态数据成员多文件写法
error LNK2019:
无法解析的外部符号 "public: __cdecl MM::~MM(void)" (??1MM@@QEAA@XZ),函数 main 中引用了该符号
//1.无法解析: 没有实现这个函数
//2. "public: __cdecl MM::~MM(void)" (??1MM@@QEAA@XZ)
//2.1 public:权限
//2.2 __cdecl:调用准备
//2.2 MM::~MM(void): 函数名
error C2572: “MM::initData”: 重定义默认参数 : 参数 1
//重定义问题: 多次定义
小试牛刀
//自己总结特殊成员的特性,写出测试代码