方法:c++98,通过私有且只申明不实现拷贝构造与赋值函数,从而实现该类不能被拷贝。c++11引入关键字delete后,可以使构造构造与赋值函数等于delete。效果也是无法被拷贝。
方法一,析构私有化
//实现一个类,智能在堆上创建对象
class HeapCreat
{
public:
HeapCreat()
{
cout << "调用构造" << endl;
}
void release()
{
delete this;
}
private:
//方法一 析构函数私有化
~HeapCreat()
{
cout << "调用析构" << endl;
}
方法二,构造私有化
class HeapCreat
{
public:
~HeapCreat()
{
cout << "调用析构" << endl;
}
void release()
{
delete this;
}
static HeapCreat* Creat()
{
return new HeapCreat;
}
//但是要禁用拷贝构造,拷贝出都在栈上,不在堆上
HeapCrea(const HeapCrea& p)=delete;
private:
HeapCreat()
{
cout << "调用构造" << endl;
}
//方案二 构造函数私有化
};
int main()
{
//构造函数私有化,最开始都初始化不了,因此只能在类里初始化,并且申明为全局,之后调用类里的初始化
HeapCreat* p = HeapCreat::Creat();
p->release();
return 0;
}
方法一:
还是构造私有化,但是注意拷贝构造,我们拷贝构造可以new,但拷贝构造不能禁用,因为我们需要调用拷贝构造,故有缺陷
//构造私有化
//还是控制构造函数,在类中实现只能在栈上创建。
class HeapCreat
{
public:
~HeapCreat()
{
cout << "调用析构" << endl;
}
static HeapCreat Creat()
{
return HeapCreat();
}
HeapCreat( HeapCreat& p)=delete;
private:
HeapCreat()
{
cout << "调用构造" << endl;
}
};
int main()
{
HeapCreat p = HeapCreat::Creat();
return 0;
}
方法二,直接不让使用new,申明出new并私有化,或delete.
class HeapCreat
{
public:
~HeapCreat()
{
cout << "调用析构" << endl;
}
static HeapCreat Creat()
{
return HeapCreat();
}
void* operator new(size_t t) = delete;
private:
//void* operator new(size_t t)
HeapCreat()
{
cout << "调用构造" << endl;
}
};
同上,构造函数私有化,调不了就无法被继承。
c++11提供了关键字final,可以是这个类不能为继承,即最终类。
c语言的类型转换分为两种:
1.隐式类型转换? :int i=1;double b=i;
对于能相互转换的类型,可以隐式类型转换。
2.显式类型转换 :? int j=1;doule ret=double(j)/0.1;
有关联性的类型可以强制类型转换。
对于c语言的类型转换,c++认为不太规范,因此c++提出了四种强制类型转换的类型,只有这四类的类型才能强转。
C++提供了四种强制类型转换的函数:static_cast、dynamic_cast、const_cast和reinterpret_cast。
下面对这四种转换操作的适用场景分别进行说明:
static_cast(静态转化): 该运算符把 expression 转换为 type 类型,主要用于基本数据类型之间的转换,如把 uint 转换为 int,把 int 转换为 double 等。此外,还可用于类层次结构中,基类和派生类之间指针或引用的转换。
主要用于相近类型的转化(对应c语言的隐式类型转换的类型):
double i = 3.14159265;
int j = static_cast<int> (i) ;
dynamic_cast:(动态转化) 主要用于类层次间的上行转换或下行转换。在进行上行转换时dynamic_cast 和 static_cast 的效果是一样的,但在下行转换时,dynamic_cast 具有类型检查的功能,比 static_cast 更安全。
const_cast:(常态转化) 该运算符用来修改 expression 的 const 或 volatile 属性。
去调const属性,取地址在强转为普通指针类型。
const int a = 10;
int* p = const_cast<int*>(&a);
*p = 3;
这里的a可能直接放寄存器了,也可能宏定义了。(不再去内存找这个值)?
因此虽然这里&a与p的地址一样,但是值不一样。利用关键字volatile使得强制去内存取值,我们就会发现两个值是一样的。其次在打印&a时,注意用printf,c++中的cout的输出流在打印时没有对应的函数。
reinterpret_cast: (重新诠释转化)该运算符可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。这个转换是“最不安全”的,不推荐使用
有一定关联,但是意义不相似的类型之间的转换
int a = 1;
int* ptr = reinterpret_cast<int*> (a);
注意:类型转换中间会产生临时变量,二临时变量具有常性,是不能被修改的(引用)。