重庆网站建设制作设计,wordpress cros,怎么做应援网站,室内装潢目录
一、特殊类
1.1拒绝被拷贝的类
1.2 限制在堆上创建类
1.3 限制在栈上创建的类
1.4 不能被继承的类
二、类型转换
2.1 static_cast
2.2 reinterpret_cast
2.3 const_cast
2.4 dynamic_cast 一、特殊类
什么是特殊类#xff1f;在普通类的设计基础上#xff0c…目录
一、特殊类
1.1拒绝被拷贝的类
1.2 限制在堆上创建类
1.3 限制在栈上创建的类
1.4 不能被继承的类
二、类型转换
2.1 static_cast
2.2 reinterpret_cast
2.3 const_cast
2.4 dynamic_cast 一、特殊类
什么是特殊类在普通类的设计基础上提出一些限制条件设计的类就是特殊类。
1.1拒绝被拷贝的类
拷贝只会发生在两个场景中拷贝构造函数以及赋值运算符重载。
禁止拷贝的类只需要让该类禁止调用拷贝构造函数和赋值运算符重载函数即可。
在C98中常用如下方式
class CopyBan
{
public:CopyBan(){}
private:CopyBan(const CopyBan cb);//拷贝构造函数声明CopyBan operator(const CopyBan cb);//赋值运算符重载声明
};将拷贝构造函数和赋值运算符重载函数只声明不定义并且设置成私有。
原因 只声明不定义在调用拷贝构造和赋值运算符重载函数的时候由于没有定义就会产生链接错误在编译阶段就报错。 设置成私有防止在类外定义拷贝构造和赋值运算符重载函数此时即使定义了因为私有的原因在类外也无法调用
C11新方法 使用C11中的给delete新赋予的意义来禁止生产拷贝构造和赋值运算符重载函数。
此时编译器也不会自动生成默认的拷贝构造和赋值运算符重载函数。
1.2 限制在堆上创建类
正常创建类对象时会在栈上创建并且自动调用构造函数来初始化。
只能在创建在堆上时就需要让该对象只能通过new来创建并且调用构造函数来初始化。 定义一个静态成员函数在该函数内部new一个Heaponly对象。将构造函数和拷贝构造函数私有并且禁止生成拷贝构造函数。
非静态成员函数在调用的时候必须使用点(.)操作符来调用这一步是为了传this指针。
这样的前提是先有一个HeapOnly对象但是构造函数设置成了私有就无法创建这样一个对象。
而静态成员函数的调用不用传this指针也就不用必须有HeapOnly对象只需要类域::静态成员函数即可。
静态成员函数属于HeapOnly域内所以在new一个对象的时候可以调用私有的构造函数。
1.3 限制在栈上创建的类
主要要做到不能在堆上创建类对象。new一个对象的时候会调用该类的operator new(size_t size)函数在释放资源的时候又会调用该类的operator delete(void* p)函数。
方法1
所以防止在堆上创建类对象就是要禁止调用这两个函数。
class StackOnly
{
public://构造函数StackOnly(){}void* operator new(size_t size) delete;//禁止调用newvoid operator delete(void* p) delete;//禁止调用delete
};使用delete来禁止这两个函数的调用那么在new一个对象的时候就会产生编译错误从而无法在堆区上创建类对象。 方法2
class StackOnly
{
public:static StackOnly CreateObject(){return StackOnly();}
private:StackOnly(){}
};另一种方式就是和之前一样通过一个静态成员函数在栈区上创建一个类对象并且将默认构造函数私有化。
设计特殊类的核心点只能通过静态成员函数来创建类封掉其他所有创建方式。
1.4 不能被继承的类
C98方式
//基类
class NonInherit
{
private://基类构造函数私有NonInherit(){}
};//派生类
class B :public NonInherit
{};基类的构造函数私有派生类在创建对象的时候无法调用基类的构造函数。
C11添加了 final 关键字
class NonInherit final
{}二、类型转换
在C语言中如果赋值运算符()两边的类型不同或者形参和实参类型不匹配或者返回值类型和接收值类型不一致就需要发生类型转换。 C语言中有两种类型转换 隐式类型转换编译器在编译阶段自动进行能转就转不能转就编译失败。显式类型转换需要用户自己处理。 int main()
{int i 1;double d i;//隐式类型转换printf(%d, %.2f\n, i, d);int* p i;int address (int)p;//显式类型转换printf(%x, %d\n, p, address);return 0;
}但是C语言的类型转换存在如下缺陷
隐式类型转换有些情况下会出现问题比如数据精度发生丢失(整形提升等)。显式类型转换将所有情况混合在一起代码不够清晰。
所以C提出了自己的类型转换风格但是仍然可以使用C语言的转换风格因为要兼容C语言。
2.1 static_cast C语言的隐式类型转换在C中就可以使用static_cast来转换但是不能用于两个不相关的类型进行转换。 double d 3.14;
int a static_castint(d);static_cast 后的里放要转换的类型()里放被转换的类型。
2.2 reinterpret_cast C语言的显式类型转换在C中就可以reinterpret_cast用于将一种类型转换为另一种不同的类型。 int a 1;
int* pa a;
int address reinterpret_castint(pa);2.3 const_cast 用在删除变量的const属性方便赋值。 const int a 2;
int* p const_castint*(a);
*p 3;const_cast 更多的是一种警示表示去除了const属性要谨慎操作。
2.4 dynamic_cast 用于将一个父类对象的指针或者引用转换为子类对象的指针或引用(动态转换)。 向上转换子类对象的指针或引用 → 父类对象的指针或引用。(不发生类型转换是语法允许的发生了切片)向下转换父类对象的指针或引用 → 子类对象的指针或引用。(用 dynamic_cast 转换是安全的)
//父类
class A
{
public:virtual void f(){}int _a 1;
};
//子类
class B : public A
{
public:int _b 2;
};在main函数中传父类指针ax给函数在函数中将A* pa父类指针接收该值然后将其强转为子类指针B*使用子类指针访问子类成员bptr-_b 4发生运行时错误。 形参A* pa是父类指针接收的也是父类指针所以强转成子类指针后访问子类成员_b会发生越界。
解决方法使用dynamic_cast将父类指针强转为父类指针。
注意
dynamic_cast只能用于父类含有虚函数的类。dynamic_cast会先检查是否能转换成功能成功则转换不能则返回nullptr。dynamic_cast是安全的直接使用C语言的转换方式是不安全的。