• C++ Primer笔记2_四种类型转换_异常机制


    1.类型转换

    命名的强制类型转换:

    有static_cast、dynamic_cast、const_cast、reinterpret_cast


    static_cast:

    编译器隐式运行的不论什么类型转换都能够由static_cast完毕

    当一个较大的算术类型赋值给较小的类型时。能够用static_cast进行强制转换。

    能够将void*指针转换为某一类型的指针

    能够将基类指针强制转换为派生类指针,可是不安全。
    无法将const转化为nonconst。这个仅仅有const_cast才干够办得到

    举例:

    double d = static_cast<double>(j) / i;
    
    void *p = &d;
    double *dp = static_cast<double*>(p);

    const_cast:
    用来移除对象的常量性(cast away the constness), const_cast一般用于指针或者引用。

    对于将常量对象转换为很常量对象的行为,一旦去掉了const性质。编译器就不再阻止我们对该对象的写操作,结果是没有定义的。

    const char *pc;
    char *p = const_cast<char*>(pc);//正确:可是通过p写值是没有定义的行为;
    
    

    char *p = static_cast<char *>(pc);//错误。static_cast不能转换掉const性质
    static_cast<string>(pc);//正确。字符串字面值转换为string
    const_cast<string>(pc);//错误,const_cast仅仅改变常量属性


    看以下一个样例:

    #include <iostream>
    using namespace std;
    
    int main(void)
    {
    	const int a = 100;
    	int *pA = const_cast<int *>(&a);
    	*pA = 200;
    
    	int &refA = const_cast<int &>(a);
    	refA = 300;
    
    //	int *pA1 = static_cast<int *>(&a);  Error 
    
    	cout << "*pA:" << *pA << endl;//300
    	cout << "refA:" << refA << endl;//300
    	cout << "a:" << a << endl;//100
    
    	return 0;
    }

    发现通过const_cast转换后,去除了const属性,然后对变量改动,执行时内存中的值是改变的,但最后打印改动后的值仍为原样。

    以下是网上摘录的一段解释:

    const仅仅是告诉编译器不能改动而不是真正地不可改动,假设程序猿不注意而去改动了它会报错。如今我们利用const_cast去除了常量性,然后通过指针和引用对其进行了改动,所以通过指针打印或者引用传參的时候就能看出其内存确实变化了,但为了保护val这个变量本来的const特性,所以每次我们使用val时。系统都将其替换成初始值100,确保了val还是“不可变”的


    reinterpret_cast

    常为运算对象的位模式提供较低层次上的又一次解释。

    举例:

    int *pi;
    char *pc = reinterpret_cast<char *>(pi);
    我们必须牢记pc所指的真实对象是一个int而非字符,假设把pc当成字符指针在执行时可能出错。

    如:string str(pc);

    使用reinterpret_cast时很危急的,一般避免使用。



    dynamic_cast:

    dynamic_cast主要用于类层次间的上行转换和下行转换,还能够用于类之间的交叉转换。
    在类层次间进行上行转换时。dynamic_cast和static_cast的效果是一样的。
    在进行下行转换时。dynamic_cast具有类型检查的功能,比static_cast更安全。

    1. 安全的基类和子类之间转换。


    2. 必需要有虚函数。


    3. 同样基类不同子类之间的交叉转换。但结果是NULL。

    样例:

    #include <iostream>
    using namespace std;
    
    class A
    {
    	protected:
    	int n;
    	public:
    		A(){n = 10;}
    		virtual void getN(){}
    };
    
    class B : public A
    {
    	string name;
    	public:
    		B(){name = "SCOTT";}
    		virtual void getN()
    		{
    			cout << "B: " << n << endl;
    		}
    		void printf()
    		{
    			cout << "name: " << name << endl;
    		}
    };
    
    void Test(A * pA)
    {
    	B *pB1 = static_cast<B *>(pA);
    	cout << "pB1: " << pB1 << endl;
    
    	B *pB2 = dynamic_cast<B *>(pA);
    	cout << "pB2: " << pB2 << endl;
    }
    
    int main()
    {
    	A *pA1 = new A;
    	A *pA2 = new B;
    	
    	Test(pA1);//pB2为空指针 dynamic_cast将做类型检查,pB1尽管正确,但对其操作是不安全的,从这里能够看出static_cast没有dynamic安全
            Test(pA2);//OK 都是B类型对象
    
    	return 0;
    }


    总结:

    去掉const属性用const_cast

    主要的类型转换用static_cast

    多态类之间的类型转换用dynamic_cast

    不同类型指针类型转换用reinterpret_cast


    參考:

    http://blog.csdn.net/ljz888666555/article/details/4541232

    http://blog.csdn.net/jnu_simba/article/details/8868530


    2.异常机制

    try-catch-throw的使用:

    #include <iostream>
    
    using namespace std;
    
    double fun(int a, int b)
    {
    	if(0 == b)
    	{
    		throw b;
    	}
    	return a/b;
    }
    
    int main()
    {
    	double a = 0.0;
    
    	try
    	{
    		a = fun(2, 0);
    	}
    	catch(int)
    	{
    		cout << "Error: b is zero!" << endl;
    	}
    	catch(...)
    	{
    		cout << "Other error!" << endl;
    	}
    	cout << "a: " << a << endl;//still run after deal exception
    
    	return 0;
    }

    自己定义异常类:

    #include <iostream>
    using namespace std;
    
    class MyException
    {
    	public:
    		MyException(string name = "default name")
    		{
    			cout << "New Exception: " << name << endl;
    			this->name = name;
    		}
    		~MyException()
    		{
    			cout << "Delete Exception: " << this->name << endl;
    		}
    		void myThrow()
    		{
    			throw MyException("Error");
    		}
    	private:
    		string name;
    };
    
    int main()
    {
    	MyException m("Test");
    	try
    	{
    		m.myThrow();
    	}
    	catch(...)
    	{
    		cout << "*****" << endl;
    	}
    
    	return 0;
    }
    执行结果:

    New Exception: Test
    New Exception: Error
    *****
    Delete Exception: Error
    Delete Exception: Test


  • 相关阅读:
    unity vscode 断点问题
    unity Prefab 序列化一个小问题。
    公司有同事中病毒
    有点愧疚,今天把unity官方骗了...
    网络处理,发送约定
    (转载)MonoBehaviour的事件和具体功能总结
    控制台输出乱码问题
    vs遇到的字符串问题
    cmake的下载和安装
    三消设计思路, 通过配置文件搞定一切。
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/6784575.html
Copyright © 2020-2023  润新知