建设银行面试经验网站,南充网站建设略奥,网页设计实践报告,中国114黄页网站宣传广告目录
一#xff0c;特殊类设计
1. 只在堆上创建的类
2. 只允许在栈上创建的类
3. 不能被继承的类
4. 不能被拷贝的类 5. 设计一个类#xff0c;只能创建一个对象#xff08;单例对象#xff09;
饿汉模式
懒汉模式
C11静态成员初始化多线程安全问题
二#xff…目录
一特殊类设计
1. 只在堆上创建的类
2. 只允许在栈上创建的类
3. 不能被继承的类
4. 不能被拷贝的类 5. 设计一个类只能创建一个对象单例对象
饿汉模式
懒汉模式
C11静态成员初始化多线程安全问题
二 C类型转换
C语言类型转换存在的问题
1. static_cast近似类型
2. reinterpret_cast(不相关类型)
3. const_cast
4. dynamic_cast一般用于多态
5. RTTI了解
结语 嗨收到一张超美的风景图愿你每天都能顺心 一特殊类设计
1. 只在堆上创建的类 实现方式 1. 将类的构造函数私有拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。 2. 提供一个静态的成员函数在该静态成员函数中完成堆对象的创建 // 方法一
class HeapOnly
{
public:void Destory(){cout ~HeapOnly endl;delete this;}private:~HeapOnly(){}int i;
};
// 将析构函数设为私有这样在栈中的对象(不需要手动析构)在栈结束时
// 无法自动调用析构函数。// 方法二构造函数私有仅提供一个creat函数来进行构造
class HeapOnly_2
{
public:// static 添加原因我们知道调用成员函数需要对象但我们这时并没有对象// 因此需要用static修饰。(先有鸡先有蛋问题)static HeapOnly_2* creat_(int b) {return new HeapOnly_2(b);}// 防止默认拷贝赋值构造生成在栈上创建HeapOnly_2(const HeapOnly_2 b) delete;HeapOnly_2 operator(const HeapOnly_2 b) delete;
private:HeapOnly_2(int b):i(b){}int i;
};int main()
{// HeapOnly it;HeapOnly* it new HeapOnly;it-Destory();//HeapOnly_2 it2;HeapOnly_2* it2 HeapOnly_2::creat_(1);//HeapOnly_2 it3 *it2; //HeapOnly_2 it3(*it2);delete it2return 0;
} 2. 只允许在栈上创建的类
class StackOnly
{
public:static StackOnly creat_(int b){return StackOnly(b); //意味着拷贝构造不能禁止 }// creat_返回值是右值我们拷贝构造参数只设置右值,同时默认构造也不会产生StackOnly(StackOnly st):_i(st._i){}//但这也没有禁止move一下就又可以了private:// 构造一私有堆栈上都无法构造创建StackOnly(int i):_i(i){}StackOnly operator(const StackOnly st) delete;int _i;
};
方法同1类似但这无法限制住static对象的拷贝。 3. 不能被继承的类
C98方式将构造函数私有派生类无法调用到构造函数导致无法被继承。
// C98中构造函数私有化派生类中调不到基类的构造函数。则无法继承
class NonInherit
{
public:static NonInherit GetInstance(){return NonInherit();}
private:NonInherit(){}
};
C11新方式在目标类添加关键词——final表示该类无法被继承。
class A final
{// ....
}; 4. 不能被拷贝的类
拷贝只会放生在两个场景中拷贝构造函数以及赋值运算符重载因此 想要让一个类禁止拷贝只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。 C98 将拷贝构造函数与赋值运算符重载只声明不定义并且将其访问权限设置为私有即可 。 class CopyBan
{// ...private:CopyBan(const CopyBan);CopyBan operator(const CopyBan);//...
}; 原因 1. 设置成私有如果只声明没有设置成private用户自己如果在类外定义了就可以不能禁止拷贝了 2. 只声明不定义不定义是因为该函数根本不会调用定义了其实也没有什么意义不写反而还简单而且如果定义了就不会防止成员函数内部拷贝了。 C11 C11扩展delete的用法delete除了释放new申请的资源外如果在默认成员函数后跟上delete表示让编译器删除掉该默认成员函数。 class CopyBan
{// ...CopyBan(const CopyBan)delete;CopyBan operator(const CopyBan)delete;//...
}; 5. 设计一个类只能创建一个对象单例对象 设计模式 设计模式Design Pattern是一套 被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。我们学过的有适配器迭代器包装器以及扩展工厂观察者模式。下面的单例模式也是 。 单例模式 一个类只能创建一个对象即单例模式该模式可以保证系统中该类只有一个实例并提供一个访问它的全局访问点该实例被所有程序模块共享。比如在某个服务器程序中该服务器的配置信息存放在一个文件中这些配置数据由一个单例对象统一读取然后服务进程中的其他对象再通过这个单例对象获取这些配置信息这种方式简化了在复杂环境下的配置管理。单例模式有两种实现模式 饿汉模式 就是说不管你将来用不用程序启动时就先创建一个唯一的实例对象 。 class SingleCase
{
public:static SingleCase* GetInstace(){return _sc;}size_t GetSize(){return _vc.size();}void Add(const string str){_mtx.lock();_vc.push_back(str);_mtx.unlock();}void print(){for (auto it : _vc){cout it endl;}}SingleCase(const SingleCase it) delete;SingleCase operator(const SingleCase it) delete;
private:SingleCase(){}mutex _mtx;vectorstring _vc;static SingleCase* _sc;
};
// 声明定义分离_sc是也在类成员中(能调用类成员)虽然看起来像在类外。
SingleCase* SingleCase::_sc new SingleCase; 饿汉的缺点 1. 单例对象的构造可能会占用大量资源对应用程序的打开比较慢。 2. 不适合多个单例对象之间存在依赖关系生成。如单例A单例B必须得先有A再有B,如果在同一个源文件中跟声明顺序相同但如果不在同一个源文件中产生顺序就不确定。 优点代码简单支持一些高并发场景 懒汉模式 如果单例对象构造十分耗时或者占用很多资源比如加载插件啊 初始化网络连接啊读取文件啊等等而有可能该对象程序运行时不会用到那么也要在程序一开始就进行初始化就会导致程序启动时非常的缓慢。 所以这种情况使用懒汉模式 延迟加载更好。 class SingleCase_lazy
{
public:static SingleCase_lazy* GetInstace(){// 处理大多数情况提高效率if (_sc nullptr){SingleCase_lazy::new_mtx.lock();// 两程序几乎同一时间进入该// 作用域时再进行判断if (_sc nullptr) {// 加锁防止_sc发生覆盖_sc new SingleCase_lazy;}SingleCase_lazy::new_mtx.unlock();}return _sc;}size_t GetSize(){return _vc.size();}void Add(const string str){_vmtx.lock();_vc.push_back(str);_vmtx.unlock();}void print(){for (auto it : _vc){cout it endl;}}static void Destory(){new_mtx.lock();if (_sc){cout delete _sc endl;}new_mtx.unlock();delete _sc;}class De{public:~De(){Destory();}};SingleCase_lazy(const SingleCase_lazy it) delete;SingleCase_lazy operator(const SingleCase it) delete;
private:SingleCase_lazy(){}static mutex new_mtx;mutex _vmtx;vectorstring _vc;static SingleCase_lazy* _sc; //无法显示调用析构,我们通过内部类调用
};
SingleCase_lazy* SingleCase_lazy::_sc nullptr;
mutex SingleCase_lazy::new_mtx; // 静态函数的锁
SingleCase_lazy::De _de;
总结设计一个单例对象我们需要满足1. 把数据放一个类中把这个类设计成单例类。 2. 保持进程唯一需要将拷贝赋值都禁止。 3. 设计模式是饿汉还是懒汉
C11静态成员初始化多线程安全问题
class SingleInstance {
public:static SingleInstance* GetInstance() {// 局部静态变量实现的懒汉式单例C11后线程安全// 在C11之前不能保证多线程安全static SingleInstance instance;return instance;}
private:SingleInstance();~SingleInstance();SingleInstance(const SingleInstance signal) delete;SingleInstance operator(const SingleInstance signal) delete;
}; 二 C类型转换 标准C为了加强类型转换的可视性引入了四种命名的强制类型转换操作符 static_cast、reinterpret_cast、const_cast、dynamic_cast C语言类型转换存在的问题 C风格的转换格式很简单但是有不少缺点的 1. 隐式类型转化有些情况下可能会出问题比如数据精度丢失 2. 显式类型转换将所有情况混合在一起代码不够清晰 因此C提出了自己的类型转化风格注意因为C要兼容C语言所以C中还可以使用C语言的转化风格。 1. static_cast近似类型 static_cast用于非多态类型的转换静态转换编译器隐式执行的任何类型转换都可用static_cast但它不能用于两个不相关的类型进行转换。 int main()
{double d 12.34;int a static_castint(d);coutaendl;return 0;
} 2. reinterpret_cast(不相关类型) reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释用于将一种类型转换为 另一种不同的类型 int main()
{double d 12.34;int a static_castint(d);cout a endl;// 这里使用static_cast会报错应该使用reinterpret_cast//int *p static_castint*(a);int *p reinterpret_castint*(a);return 0;
}
3. const_cast const_cast 最常用的用途就是删除变量的 const 属性方便赋值 int main()
{volatile const int i 10;int* it const_castint*(i);*it 2;cout i endl; // 10cout *it endl; // 2// i为什么没有被修改答i被编译器优化i被10替换到寄存中并没有在内存中获取//在C中volatile关键字用于告诉编译器该变量的值可能会在程序的控制之外被改变//因此编译器不应该对该变量进行优化。这意味着每次访问该变量时编译器都会从内存// 中读取最新的值而不是使用之前缓存的值 来自gpt的回答return 0;
}
4. dynamic_cast一般用于多态 dynamic_cast 用于将一个父类对象的指针 / 引用转换为子类对象的指针或引用 ( 动态转换 ) 注意 1. dynamic_cast 只能用于父类含有 虚函数 的类。 2. dynamic_cast会先检查是否能转换成功能成功则转换不能则返回0。
class A
{
public :
virtual void f(){}
};
class B : public A
{};
void fun (A* pa)
{
// dynamic_cast会先检查是否能转换成功能成功则转换不能则返回
B* pb1 static_castB*(pa);
B* pb2 dynamic_castB*(pa);
coutpb1: pb1 endl;
coutpb2: pb2 endl;
}
int main ()
{A a;B b;fun(a);fun(b);return 0;
}
5. RTTI了解 RTTI Run-time Type identification 的简称即 运行时类型识别 。 C 通过以下方式来支持 RTTI 1. typeid 运算符获取类型 2. dynamic_cast 运算符 3. decltype 结语 本小节就到这里了感谢小伙伴的浏览如果有什么建议欢迎在评论区评论如果给小伙伴带来一些收获请留下你的小赞你的点赞和关注将会成为博主创作的动力