正文

C++转型操作符2008-06-06 22:42:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/rickone/35971.html

分享到:

C++有四种转型操作符,以下小结一下:

1,static_cast<>()

用得最多的,如果转换的是类型,则调用转型函数:比如int转float,float转int等基本数据类型的转型,如果是一个类,就调用类型转换函数,比如:

#include <iostream>

using namespace std;

class A
{
public:
    explicit A(int _a = 0) : a(_a) {}
    operator int() const
    {
        return a;
    }
private:
    int a;
};
int main()
{
    A a(100);
    int b = static_cast<int>(a);
    cout<<b<<endl;
    system("PAUSE");
    return 0;
};

可以转换一个基类指针到子类指针的转型,但是不做动态类型检查,可以不存在虚函数,因此转型可能是不安全的,但是是快速的。

2,dynamic_cast<>()

专门用于C++类的指针转型,且是用于多态继承体系中的类。public继承体现了‘is-a’的类关系,一个基类指针,可以指向子类对象,它的子类类型是动态类型,dynamic_cast<>()就是将基类指针转型成它动态类型的子类指针,如果类型不对,结果就是空。

#include <iostream>

using namespace std;

class B
{
public:
    virtual void foo() {
        cout<<"B.foo"<<endl;
    }
};

class D1 : public B
{
public:
    void foo() {
        cout<<"D1.foo"<<endl;
    }
    void foo2() {
        cout<<"D1.foo2"<<endl;
    }
};

class D2 : public B
{
public:
    void foo() {
        cout<<"D2.foo"<<endl;
    }
    void foo3() {
        cout<<"D2.foo3"<<endl;
    }
};
int main()
{
    B *pb = new D2;
    pb->foo();
    D1 *pd1 = dynamic_cast<D1*>(pb);
    if(pd1)
    {
        pd1->foo2();
    }
    D2 *pd2 = dynamic_cast<D2*>(pb);
    if(pd2)
    {
        pd2->foo3();
    }
    delete pb;
    system("PAUSE");
    return 0;
};

(1)必须有虚接口,那么,如果用基类指针使用虚接口,则可以动态绑定,不需要转型,就能体现多态;(2)如果是子类指针,可以直接给基类指针,可以直接使用。所以使用dynamic_cast的情形比较简单,就是用基类指针使用非虚接口的情形。非虚接口体现了子类的特有操作,也就是要确定它的动态类型,如上例,给了pb指针,但不知道是D1还是D2,转型后,看结果是否非空,如果空则表示不是这个类型,然后分情况处理。它相当于使用typeid+static_cast,是安全的转型。

3,const_cast<>()

用以去掉‘数据’的常量属性,常量属性多体现在指针和引用,因为如果没有指针和引用,就不存在不小心修改了不能修改的东西。如

const int a =314;
a=2;//这个傻瓜编译器都知道你在忽悠它
int *p = &a;
*p=3;//这两句,是不是可以成功忽悠你,转了弯修改了不能修改的东西

C++会报错,因为&a是const int *,不能将一个const指针或引用赋给指针或初始化引用。换成这样就行了:

int *p=const_cast<int*>(&a);

编译器放给了你这样的权力,如果你这样写,表明你能为它的后果负责,如果出了错,如果你做的是导弹火控系统,你将会知道结果有多严重。

MSDN里有一个例子,一个const成员函数里修改this指针的常量性,这很高明,真的很高明,因为完全没有理由使用mutable关键字啦~~const成员函数的第一个参数类型是const ClassName*,简单的不同。

4,reinterpret_cast

这个我用得非常少,因为太长了,每次打都不记得。字面意思是重新解释,就是可以将任何指针转型成其它指针或者整型类型,它是底层的转型,也是不安全的。MSDN里有一个hash函数的例子比较‘高层’的运用了它。哦,对了,它不能去掉const属性。

给一个我的例子,功能是显示数据的每一个字节:

#include <cstdlib>
#include <iostream>

using namespace std;

template<typename Functor>
class for_byte
{
public:
    template<typename T>
    void operator()(T & data)
    {
        unsigned char * p = reinterpret_cast<unsigned char*>(&data);
        for(int i=sizeof(T);i>0;--i)
        {
            fun(*p++);
        }
    }
private:
    Functor fun;
};

struct display_bit
{
    void operator()(unsigned char byte)
    {
        printf("%02X",byte);
    }
};

int main(int argc, char *argv[])
{
    for_byte<display_bit> display;
    double x = 3.14;
    int y = -1;
    display(x);
    printf("\n");
    display(y);
    printf("\n");
    display(display);
    printf("\n");
    system("PAUSE");
    return EXIT_SUCCESS;
}

阅读(5866) | 评论(1)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册