当前位置: 首页 > news >正文

咨询公司企业文化台州网站建设优化案例

咨询公司企业文化,台州网站建设优化案例,进入公众号即弹出图文,建设 市民中心网站目录 一、设计一个类不能被拷贝 (一)C98 (二)C11 二、设计一个类只能在堆上创建对象 (一)将构造函数私有化,对外提供接口 (二)将析构函数私有化 三、设计一个类只…

目录

一、设计一个类不能被拷贝

(一)C++98

(二)C++11

二、设计一个类只能在堆上创建对象

(一)将构造函数私有化,对外提供接口

(二)将析构函数私有化

三、设计一个类只能在栈上创建对象

四、设计一个类不能被继承

(一)C++98

(二)C++11

五、设计一个类只能创建一个对象(单例模式)

(一)饿汉模式

(二)懒汉模式

六、类型转换

(一)C语言类型转换

(二)C++新增四种强制类型转换

1、static_cast

2、reinterpret_cast

3、const_cast

4、dynamic_cast


一、设计一个类不能被拷贝

(一)C++98

class banCopy
{
private:banCopy(const banCopy& bc);banCopy& operator=(const banCopy& bc);
};

        通过将拷贝构造以及赋值重载私有化使得外部不能调用拷贝构造以及赋值重载。但是对于内部而言仍可以进行类的拷贝。

(二)C++11

class banCopy
{banCopy(const banCopy& bc) = delete;banCopy& operator=(const banCopy& bc) = delete;
};

        通过使用关键字直接删除相关函数。

二、设计一个类只能在堆上创建对象

(一)将构造函数私有化,对外提供接口

class heapOnly
{
public:static heapOnly* createObj(){return new heapOnly;}
private:heapOnly() {};heapOnly(const heapOnly& h) = delete;heapOnly& operator = (const heapOnly& h) = delete;
};

        首先将构造函数私有化,可以禁止在栈帧以及静态区创建对象,专门提供创建堆上对象的接口。同时也需要将接口设置为静态成员函数,使得无需对象也可以直接调用该接口。

heapOnly* ph = heapOnly::createObj();

        需要注意的是,也要将拷贝构造与赋值重载删除掉,如果不进行删除,仍然可以通过拷贝对象生成在栈帧或者静态区的对象。

//若不禁用拷贝函数,即可通过拷贝仍在栈帧上生成对象
heapOnly* ph = heapOnly::createObj();
heapOnly h(*ph);

(二)将析构函数私有化

class heapOnly
{
public:heapOnly() {  };void destoy(){this->~heapOnly();}
private:~heapOnly() {  };
};

        利用类与对象的特性:局部对象出作用域会自动调用析构函数释放资源的特性,将析构函数私有化使得在栈上或静态区上开辟的对象会因此导致编译错误,只能在堆上开辟对象。

        因为在堆上开辟的对象需要手动 delete 释放资源,而使用 delete 关键字仍然会调用析构函数(私有化)而导致编译报错,因此可以提供释放资源的接口来实现资源的释放。

三、设计一个类只能在栈上创建对象

class stackOnly
{public:static stackOnly createObj(){return stackOnly();}
private:stackOnly() {  }
};

        通过构造函数私有化并提供创建对象接口实现只在栈帧上开辟空间。因此使用 new 生成对象会自动调用构造函数,又因构造函数被私有化了因此使用 new 关键字生成对象会编译报错,故禁止了在堆上开辟空间。

        但上述方法并不能禁用从静态区生成对象,仍然可以通过拷贝在静态区生成对象

static stackOnly so = stackOnly::createObj();

        如果想彻底解决以上问题则需要禁用拷贝构造,但是如果禁用了拷贝构造,就不能从 createObj() 返回生成对象了,只能生成临时对象或是临时对象的引用,但是不能修改。

stackOnly::createObj();	//临时对象
const stackOnly& so = stackOnly::createObj();	//临时对象的引用

四、设计一个类不能被继承

(一)C++98

class finalClass
{
public:static finalClass CreateObj(){return finalClass();}
private:finalClass() {  }
};

        因为子类构造函数会自动调用父类构造函数完成对父类变量的初始化,通过将父类构造函数私有化,使得子类无法调用父类的构造函数,因此使得该类无法被继承。

(二)C++11

class FinalClass final
{
};

        C++11直接使用 final 关键字使得该类无法被继承。

五、设计一个类只能创建一个对象(单例模式)

(一)饿汉模式

class InfoSingleton
{
public://返回私有静态成员static InfoSingleton& GetInstance(){return _sins;}void insert(string name, int salary){_um[name] = salary;}void Print(){for (auto& e : _um){cout << e.first << ":" << e.second << endl;}cout << endl;}
private://构造函数私有化InfoSingleton(){}//删除拷贝构造以防新建对象InfoSingleton(const InfoSingleton& sins) = delete;InfoSingleton& operator=(const InfoSingleton& sins) = delete;//示例功能 无特殊含义unordered_map<string, int> _um;//定义静态类型成员static InfoSingleton _sins;
};InfoSingleton InfoSingleton::_sins;	//初始化静态变量int main()
{//下列代码可证明返回的是同一个对象InfoSingleton& sins1 = InfoSingleton::GetInstance();sins1.insert("张三", 15000);sins1.insert("李四", 20000);sins1.insert("王五", 10000);sins1.insert("赵六", 30000);sins1.Print();InfoSingleton& sins2 = InfoSingleton::GetInstance();sins2.insert("赵六", 20000);sins2.Print();return 0;
}

        以上是利用所有对象公用一个类静态成员的特性,通过私有构造函数以及删除拷贝函数给出静态类型成员变量的静态接口函数,使得该类只能通过该接口返回静态成员对象

        因为静态成员变量需要在类外进行初始化,而在初始化的同时会自动调用构造函数进行初始化。因此该静态成员对象的初始化,也就是调用构造函数会在main函数之前。

InfoSingleton InfoSingleton::_sins;	//初始化静态变量

        饿汉模式的特点:

        1、 单例对象初始化时,数据太多会导致启动慢;

        2、如果多个单例类有初始化的依赖关系,饿汉模式无法控制。例如A和B都是单例类,因为B的启动依赖A,所以需要先初始化A,再初始化B,但是饿汉模式无法控制对象的初始化顺序;

        3、饿汉模式创建的对象不会有线程安全问题,因为该模式的对象在main函数之前已经被创建好了,而mian函数之前线程都没启动。

(二)懒汉模式

class InfoSingleton
{public://返回私有静态成员static InfoSingleton& GetInstance(){if (_sins == nullptr){_sins = new InfoSingleton;}return *_sins;}void insert(string name, int salary){_um[name] = salary;}void Print(){for (auto& e : _um){cout << e.first << ":" << e.second << endl;}cout << endl;} 
private://构造函数私有化InfoSingleton(){}//删除拷贝构造以防新建对象InfoSingleton(const InfoSingleton& sins) = delete;InfoSingleton& operator=(const InfoSingleton& sins) = delete;//示例功能 无特殊含义unordered_map<string, int> _um;//定义静态类型成员static InfoSingleton* _sins;
};
InfoSingleton* InfoSingleton::_sins = nullptr; //初始化静态变量int main()
{//下列代码可证明返回的是同一个对象InfoSingleton& sins1 = InfoSingleton::GetInstance();sins1.insert("张三", 15000);sins1.insert("李四", 20000);sins1.insert("王五", 10000);sins1.insert("赵六", 30000);sins1.Print();InfoSingleton& sins2 = InfoSingleton::GetInstance();sins2.insert("赵六", 20000);sins2.Print();return 0;
}

        同样的,私有构造函数以及删除拷贝函数并提供生成对象接口都是为了单例模式做准备,与饿汉模式类同。        

        与饿汉模式不同的是,懒汉模式封装的是静态对象指针,也就是在 createObj() 函数第一次进入时会在堆区新建一个对象,而之后的进入则是返回该对象,以此实现只能生成一个对象。

        但是以上的代码存在线程安全问题,多个线程进入 createObj() 函数可能会导致多个线程都会在堆上新建对象导致内存泄漏,因此需要对以上接口进行修改。

class InfoSingleton
{public://返回私有静态成员static InfoSingleton& GetInstance(){if (_sins == nullptr){_mutex.lock();if (_sins == nullptr){_sins = new InfoSingleton;}_mutex.unlock();}return *_sins;} 
private:static mutex _mutex;
};

        将 _sins 的检查以及赋值进行加锁保护,这里进行了两层 if 进行条件判断。

        如果只有内部一层 if 判断,会导致每个线程进入该函数都会先加锁,进行判断操作后再解决,降低了系统性能。

        在外层再加一个 if 判断,当第一个线程进入时正常加锁判断操作,但是当之后的线程进入以后,再遇到第一个 if 判断后因为此时 _sins 不为空而无需进行加锁判断了,直接返回 _sins 即可,提高了性能效率。

        懒汉模式的特点:

        1、对象在main函数之后才会创建

        2、可以主动控制对象的创建时机。

        3、创建对象时存在线程安全问题,因此需要用户进行保护控制。

六、类型转换

(一)C语言类型转换

        在C语言中,如果赋值运算符两边类型不同,或是函数形参实参类型不同,或是函数返回值和接收值类型不同时等情况都会发生类型转换。C语言中共有两种形式的类型转换:显式类型转换或是隐式类型转换。

int main()
{int a = 0;//隐式类型转换double b = a;int* pa = &a;//显示类型转换int c = (int)pa;return 0;
}

        C语言的类型转换可能会存在一些问题,例如精度丢失或是隐式转换可能带来一些隐藏的bug等,因此C++提出了新的类型转换方式。

(二)C++新增四种强制类型转换

1、static_cast

        static_cast 常用于非多态类型的转换,在C语言中能隐式转换的都可以使用 static_cast 进行转换,其主要用于相近类型转换

int main()
{double a = 1.1;int b = static_cast<int>(a);std::cout << b << std::endl;return 0;
}

2、reinterpret_cast

        reinterpret_cast 用于将一种类型转换为另一种不同的类型,常用于不相关类型的转换

int main()
{int a = 1;int* pa = &a;//这里如果使用 static_cast 会编译报错int b = reinterpret_cast<int>(pa);std::cout << b << std::endl;return 0;
}

3、const_cast

        const_cast 用于对具有 const 属性的变量进行转换,常用于删除变量的const属性,方便赋值

int main()
{//volatile const int a = 1;const int a = 1;int* b  = const_cast<int*>(&a);++(*b);std::cout << a << std::endl << *b << std::endl;return 0;
}

        以上代码运行结果为 1 2,使用const_cast 取消了变量 a 的常量属性,但指针 b 仍然指向变量 a 在内存中的位置,因此可以通过指针 b 修改内存中 a 的值。

        对于最后的运行结果在不同平台下的运行结果可能不同,因为编译器对 const 变量会有优化,认为 const 变量在运行中不会改变,因此将 const 变量存入寄存器或告诉缓存中,方便访问读取。而通过指针 b 修改的值实际是修改了于内存中的值,因此打印结果不同。

        可以使用 volatile 关键字保持内存可见性,编译器将取消以上优化仍从内存读取 const 变量,因此加入关键字后打印输出的值相同。

4、dynamic_cast

        以上三种类型转换实际在C语言中已经存在,只是将其更加规范化。

        dynamic_cast 用于将一个父类的指针或引用转换为子类对象的指针或引用。

        向上转型:子类对象指针或引用 -> 父类对象指针或引用 (无需进行转换,发生切片)

        向下转型:父类对象指针或引用 -> 子类对象指针或引用 (使用 dynamic_cast 进行类型转换)

        需要注意的是:dynamic_cast 只能用于父类含有虚函数的类,如果转换失败会返回0。

class A
{
public:virtual void func() { }
};
class B : public A
{
};
void function(A* pa)
{B* pb1 = static_cast<B*>(pa);B* pb2 = dynamic_cast<B*>(pa);std::cout << "pb1:" << pb1 << std::endl;std::cout << "pb2:" << pb2 << std::endl;
}
int main()
{A a;B b;function(&a);function(&b);return 0;
}

        以下是上述代码的运行结果,我们来简要分析以下:

        实际上 function() 函数是一个多态调用。如果传入的是类型为 B 的对象,无论是 static_cast 还是 dynamic_cast 转换都可以成功,因为函数参数指针 pa 本身指向的就是类型为 B 的对象,因此可以正常使用转换后的指针。

        但是当传入的是类型为 A 的对象, 我们可以从图可知, static_cast 转换成功了但是 dynamic_cast 转换失败指向为0,而指向为0这也符合 dynamic_cast 的特性。虽然 static_cast 转换成功了,但是在使用该转换后的指针存在着极大的风险会造成未定义行为。

        在以上场景中,相较于 static_cast, dynamic_cast 相当于多了一层检查,如果不能确保能够安全转换,那不建议使用 static_cast 进行强制类型转换。

http://www.yayakq.cn/news/405888/

相关文章:

  • 成都个人兼职做网站安装wordpress注意什么
  • 优秀网站案列查询网
  • 阿里云网站怎么备案域名铜陵网站建设推广
  • 上海网站设计费用德州软件开发公司
  • 网站做用户记录湛江网站建设制作费用
  • 织梦宠物网站模板中国第一营销网
  • 网站建设总体说明书app开发语言
  • 网站的建设与板块帮传销组织做网站
  • 视频网站开发防止盗链解决wordpress占用内存
  • 网站制作多少钱新闻宝塔安装wordpress不成功
  • 做网站模板的网页名称是m开头西安网站建设联系电话
  • 网站制作用什么语言一个大佬做的本子网站
  • 网站流量好难做恒华大厦做网站公司
  • 怎样能让百度搜到自己的网站撩人的网站怎么做
  • 做外包任务网站专业做室内设计的网站
  • 网站维护等厂房建设招标网站
  • 吉林省四平市网站建设生产管理软件app
  • 做宴会网站wordpress 创建分类
  • wordpress主题 yusi重庆网站建设seo优化
  • 代充网站怎么做wordpress 邮箱免验证
  • 国外平面设计师网站网站建设微商城
  • 网站建设域名怎么用游戏小程序源码
  • 网站建设需要微信账号和密码穆棱seo
  • 北师大 网页制作与网站建设 考试浙江手机网站建设
  • 自己怎么做响应式网站做网站用到什么技术
  • 手机端网站设计尺寸手机怎样创建网站
  • 山东住房建设厅官网站首页wordpress 设置图片大小
  • 帮人做网站 怎么收费免费加盟游戏代理
  • 网站空间管理系统vi视觉形象设计
  • 国际设计网站有哪些公司静态网站模板