关于c++:C面试八股文staticcast了解一下

某日二师兄加入XXX科技公司的C++工程师开发岗位第20面:

面试官:C++中反对哪些类型转换?

二师兄:C++反对C格调的类型转换,并在C++11引入新的关键字标准了类型转换。

二师兄:C++11引入四种新的类型转换,别离是static_castdynamic_castconst_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为什么还要引入新的类型转换关键字?

二师兄:次要有三点,更平安、更灵便、可读性更好。

面试官:晓得什么是隐式转换吗?

二师兄:理解一些。隐式转换是指在表达式中主动进行的类型转换。比方intdouble相加,会把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++!(狗头)

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理