#学习自用#
union
共用体和结构体相似,但是共用体一次只能占用一个成员的内存,所有成员共用同一地址。
#include<iostream>
using namespace std;
union A
{int int_val;float float_val;
}a;
int main()
{a.float_val = 2.0f;cout << a.float_val << endl;cout << a.int_val << endl;cin.get();
}
这里a.int_val并不等于2,因为int_val与float_val地址相同,int_val的值其实是float_val在内存中的值。我们可以通过下面这串代码来理解。
#include<iostream>
using namespace std;
int main()
{ float b = 2.0;int a=*(int*) & b;cout << a << endl;a = b;cout << a << endl;cin.get();
}
第一个部分,int a=*(int*) & b ,是取b的地址然后强转为整型指针,再解引用赋值给a,和int_val与float_val的情况类似;而第二个部分,存在隐式转换,实际上是 a=(int )b ;这个部分的结果a=2 。
虚析构函数
虚析构函数并不是在子类中复写基类的析构函数,更像是在基类析构函数的基础上加一个析构函数。
#include<iostream>
using namespace std;
class Base
{
public:Base() { cout << "Base construct\n"; }~Base() { cout << "Base distroy\n"; }
};
class Derive:public Base
{
public:Derive() { cout << "Derive construct\n"; }~Derive() { cout << "Derive distroy\n"; }
};
int main()
{Base* base = new Base();delete base;cout << "------------\n";Derive* derive = new Derive();delete derive;cout << "------------\n";Base* poly = new Derive();delete poly;cin.get();
}
在删除poly时并没有调用Derive的析构函数,这里可能会导致内存泄漏,改进方法就是使用虚析构函数。 在基类的虚构函数名前加上virtual即可。只要一个类拥有子类,那么它的析构函数就必须是虚函数否则无法保证安全的扩展这个类。
类型转换
C++中用于类型转换的有static_cast ,reinterpret_cast,dynamic_cast,以及 const_cast,相比于C风格的类型转换,这些语句增加了一些检查功能,各自的使用也有一些限制,下面进行一些简单的介绍。
#include<iostream>
using namespace std;
int main()
{double a = 5.25;double b = (int)a + 5.3;cout << b << endl;b = static_cast<int>(a) + 5.3;cout << b << endl;cout << "------------------\n";int c = 1;b = *(double*) &c;cout << b << endl;b = *reinterpret_cast<double*>(&c);cout << b << endl;cout << "------------------\n";cin.get();
}
static_cast只能实现一些基本类型的转换比如float,int之类的,无法实现整型地址向double类型指针的转换,可以看到C风格的转换也可以实现这些功能,如果对性能有要求用C风格是最好的。
#include<iostream>
using namespace std;
class Base
{
public:virtual void prt() { cout << "Base type\n"; }virtual ~Base() { cout << "Base distroy\n"; }};
class Derive:public Base
{
public:void prt()override { cout << "Derive type\n"; }~Derive() { cout << "Derive distroy\n"; }
};
int main()
{Base* b1 = new Base();//指向父类的父类指针Base* b2 = new Derive();//指向子类的父类指针Derive* derive = dynamic_cast<Derive*>(b1);if (!derive)cout << "transmition fail\n";elsederive->prt();derive = dynamic_cast<Derive*>(b2);if (!derive)cout << "transmition fail\n";elsederive->prt();delete (b1,b2);//错误的,只删除了b2cin.get();
}
dynamic_cast用于有继承关系的转换,转换不成功会返回null,转换不成功的情况:1)两个没有继承关系的类指针之间的转换。2)下行转换(父转子)的情况中,指向父类的父类指针转换为子类指针会失败,而指向子类的父类指针可以转换为子类指针。3)上行转换不会失败。4)delete (b1,b2)涉及逗号表达式,逗号表达式的值是右值,所以只删除了b2。如果是delete b1,b2 那么就只删除b1因为逗号的优先级很低,相当于(delete b1),b2 这里b2不起作用。