某日二师兄加入XXX科技公司的C++工程师开发岗位第20面:
面试官:C++中反对哪些类型转换?
二师兄:C++反对C格调的类型转换,并在C++11引入新的关键字标准了类型转换。
二师兄:C++11引入四种新的类型转换,别离是
static_cast
、dynamic_cast
、const_cast
、和reinterpret_cast
。二师兄:
static_cast
用处最宽泛,除了前面三种类型转换外,其余的类型转换都能应用static_cast
实现。二师兄:
dynamic_cast
次要用于运行时的从父类指针向子类指针转换,如果转换不胜利则返回nullptr
。
#include <iostream>struct Base{ virtual void fun() {}};struct Derived : public Base{ virtual void fun() override {}};int main(int argc, char const *argv[]){ Base* b1 = new Base; Base* b2 = new Derived; Derived* d1 = dynamic_cast<Derived*>(b1); //d1 == nullptr Derived* d2 = dynamic_cast<Derived*>(b2); //d2 != nullptr}
二师兄:const_cast
次要用于去除指针或援用类型的const
属性。此操作可能会导致未定义的行为,所以须要慎用。
#include <iostream>void function(const int& val){ int& v = const_cast<int&>(val); v = 42;}int main(int argc, char const *argv[]){ int val = 1024; function(val); std::cout << val << std::endl; //val == 42}//-----------------------------------------------#include <iostream>static constexpr int val_static = 1024;void function(const int& val){ int& v = const_cast<int&>(val); v = 42;}int main(int argc, char const *argv[]){ function(val_static); std::cout << val_static << std::endl;}// Segmentation fault
二师兄:reinterpret_cast
能够将指针或援用转换为任何类型的指针或援用。reinterpret_cast
实现依赖于编译器和硬件,可能导致未定义的行为。
#include <iostream>int main(int argc, char const *argv[]){ int i = 42; double d = 42.0; long* l1 = reinterpret_cast<long*>(&i); long* l2 = reinterpret_cast<long*>(&d); std::cout << *l1 << std::endl; //*i1 == 42 std::cout << *l2 << std::endl; //*i2 == 4631107791820423168 X86_64 GCC 11.3 }
面试官:好的。既然曾经有C格调的类型转换,C++11为什么还要引入新的类型转换关键字?
二师兄:次要有三点,更平安、更灵便、可读性更好。
面试官:晓得什么是隐式转换吗?
二师兄:理解一些。隐式转换是指在表达式中主动进行的类型转换。比方
int
和double
相加,会把int
先转为double
,而后再进行求和。面试官:隐式转换有哪些劣势和缺点?
二师兄:隐式转换的劣势是代码简洁。然而有很大缺点,有些状况隐式转换的后果和程序员的用意不统一,会导致难以发现的问题。所以在理论我的项目中个别会增加编译选项
-Werror=conversion
来禁止隐式转换。面试官:那你晓得
explicit
关键字有什么作用吗?二师兄:也是禁止隐式转换的一个形式:
struct Foo{ Foo(int i):val_(i){} int val_;};struct Goo{ explicit Goo(int i):val_(i){} int val_;};void function1(Foo f){}void function2(Goo g){}int main(int argc, char const *argv[]){ Foo f = 1024; //编译通过,能够把int类型转换成Foo Goo g = 1024; //编译失败,不能把int类型转换成Goo function1(42); //编译通过,能够把int类型转换成Foo function2(42); //编译失败,不能把int类型转换成Goo}
面试官:如何把一个自定义类型转换成一个
int
类型?二师兄:须要重载
operator int()
运算符:
#include <iostream>struct Foo{ Foo(double d):val_(d){} double val_; explicit operator int(){ return static_cast<int>(val_); }};int main(int argc, char const *argv[]){ Foo f(42.5); int i = static_cast<int>(f); std::cout << i << std::endl; //i == 42}
面试官:好的,回去等音讯吧。
明天二师兄体现棒极了,早晨必须加个鸡腿。感激小伙伴的急躁浏览。二师兄的C++面试之旅,今天持续。
关注我,带你21天“精通”C++!(狗头)