小言_互联网的博客

[C/C++]_[初级]_[类型转换的说明]

441人阅读  评论(0)

场景

  1. C++提供了哪四种类型转换的操作符? 它们分别用在那种情况下?

说明

  1. C++提供的四种类型转换操作符是dynamic_cast,static_cast,const_cast,reinterpret_cast.

  2. 以下用例子说明它的使用场景.

main.cpp


#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include "Brass.h"
#include "BrassPlusPlus.h"
#include "BrassMinus.h"
#include <assert.h>

void TestDynamicCast()
{
    // is-a关系
    std::vector<Brass*> array;
    BrassPlus *bp = new BrassPlus();
    Brass *b = new Brass();
    BrassPlusPlus *bpp = new BrassPlusPlus();
    BrassMinus *bm = new BrassMinus();
    
    array.push_back(bp);
    array.push_back(b);
    array.push_back(bpp);
    array.push_back(bm);
    
    typedef enum Info1{
        kInfoDay = 0,
        kInfoWeek,
        kInfoMonth
    }Info;
    
    for (int i = 0; i < array.size(); ++i) {
        Brass* b = array[i];
        
        // ============ dynamic_cast ===============
        // 转换为指针类型,必须是
        BrassPlus* bp = dynamic_cast<BrassPlus*>(b);
        // 完全不相关的类型, 编译没问题.
        // AutoRelease* ar = dynamic_cast<AutoRelease*>(b);
        if(bp){
            std::cout << "b can cast to bp: " << i << " is: " << typeid(*b).name()<< std::endl;
        }else{
            std::cout << "b can't cast to bp: " << i << " is: " << typeid(*b).name() << std::endl;
        }
        
        // 转换为错误的引用类型会抛出异常
        try {
            BrassPlus& bpr = dynamic_cast<BrassPlus&>(*b);
        } catch (std::bad_cast) {
            std::cout << "*b can't cast to bpr: " << i << " is: " << typeid(*b).name() << std::endl;
        }
        
        // ============ static_cast ===============
        // static_cast可以在有父子类之间转换, 但是不判断对错, 不会为NULL.
        BrassPlus* bp1 = static_cast<BrassPlus*>(b);
        assert(bp1);
        // 不同类型的类类型之间的转换会编译错误.
        // 编译错误: Static_cast from 'Brass *' to 'AutoRelease *' is not allowed
        // AutoRelease* ar = static_cast<AutoRelease*>(b);
        // 编译错误: static_cast可以用来进行可以隐式转换的类型,比如枚举和整型,浮点和整型,父子类型; 指针和整型之间不能转换
        //int64_t s1 = static_cast<int64_t>(bp);
        Info ios1 = static_cast<Info>(2);
        
        // ============ reinterpret_cast ===============
        // 不允许删除const转换
        // 可以指针和整型互相转换, 但是被转换的类型不能转换为比它小的类型.
        int64_t addressValue = reinterpret_cast<int64_t>(b);
        std::cout << "addressValue: " << addressValue << std::endl;
        
        BrassPlus* bprc = reinterpret_cast<BrassPlus*>(b);
        assert(bprc);
        
        // 编译错误: Cast from pointer to smaller type 'int32_t' (aka 'int') loses information
        // int32_t addressValue1 = reinterpret_cast<int32_t>(b);
        // 编译错误: Reinterpret_cast from 'int' to 'Info' (aka 'Info1') is not allowed
        // Info io1 = reinterpret_cast<Info>(2);
        // Info io = reinterpret_cast<Info>(addressValue);
    }
    
    // ============ cast_cast ===============
    // 只允许去掉const,不允许类型之间的转换.
    // 修改const的值依赖于编译器,结果是不确定的. 所以基本用不到.
    const int i = 1;
    // 编译错误: Read-only variable is not assignable
    // i = 2;
    int* i1 = const_cast<int*>(&i);
    *i1 = (int)3;
    // i 的值未改到.
    std::cout << *i1 <<  ":" << i << std::endl;
    
    const int* i2 = &i;
    int* i3 = const_cast<int*>(i2);
    *i3 = (int)3;
    // i 的值未改到.
    std::cout << *i3 <<  ":" << i << std::endl;
    
    int* i4 = (int*)&i;
    *i4 = 4;
     // i 的值未改到.
    std::cout << *i4 <<  ":" << i << std::endl;
}

int main(int argc, const char * argv[])
{    
    TestDynamicCast();   
    return 0;
}

Brass.h

//
//  Brass.h
//  TestC++11
//
//  Created by sai on 8/23/19.
//  Copyright (c) 2019 sai. All rights reserved.
//

#ifndef __TestC__11__Brass__
#define __TestC__11__Brass__

#include <iostream>

class Brass
{
public:
    void TestAdd();
    void TestVirtualAdd();
    virtual ~Brass();
};

#endif /* defined(__TestC__11__Brass__) */

Brass.cpp

//
//  Brass.cpp
//  TestC++11
//
//  Created by sai on 8/23/19.
//  Copyright (c) 2019 sai. All rights reserved.
//

#include "Brass.h"
#include <libkern/OSAtomic.h>

void Brass::TestAdd()
{
    std::cout << "Brass::TestAdd" << std::endl;
}

Brass::~Brass()
{
    static int count = 0;
    OSAtomicIncrement32(&count);
    std::cout << "Brass::~Brass: " << (int64_t)this << ":" << count << std::endl;
}

void Brass::TestVirtualAdd()
{
    std::cout << "Brass::TestVirtualAdd" << std::endl;
}

BrassPlus.h

//
//  BrassPlus.h
//  TestC++11
//
//  Created by sai on 8/23/19.
//  Copyright (c) 2019 sai. All rights reserved.
//

#ifndef __TestC__11__BrassPlus__
#define __TestC__11__BrassPlus__

#include <iostream>

#include "Brass.h"

class BrassPlus: public Brass
{
public:
    void TestAdd();
    void TestVirtualAdd();
    
    ~BrassPlus();
};

#endif /* defined(__TestC__11__BrassPlus__) */

BrassPlus.cpp

//
//  BrassPlus.cpp
//  TestC++11
//
//  Created by sai on 8/23/19.
//  Copyright (c) 2019 sai. All rights reserved.
//

#include "BrassPlus.h"


void BrassPlus::TestAdd()
{
    std::cout << "BrassPlus::TestAdd" << std::endl;
}

void BrassPlus::TestVirtualAdd()
{
    std::cout << "BrassPlus::TestVirtualAdd" << std::endl;
}

BrassPlus::~BrassPlus()
{
    std::cout << "BrassPlus::~BrassPlus: " << (int64_t)this << std::endl;
}

BrassPlusPlus.h

//
//  BrassPlusPlus.h
//  TestC++11
//
//  Created by sai on 8/23/19.
//  Copyright (c) 2019 sai. All rights reserved.
//

#ifndef __TestC__11__BrassPlusPlus__
#define __TestC__11__BrassPlusPlus__

#include <iostream>

#include "BrassPlus.h"

class BrassPlusPlus: public BrassPlus
{
public:
    void TestAdd();
    void TestVirtualAdd();
    
    ~BrassPlusPlus();
};

#endif /* defined(__TestC__11__BrassPlusPlus__) */

BrassPlusPlus.cpp

//
//  BrassPlusPlus.cpp
//  TestC++11
//
//  Created by sai on 8/23/19.
//  Copyright (c) 2019 sai. All rights reserved.
//

#include "BrassPlusPlus.h"


void BrassPlusPlus::TestAdd()
{
    std::cout << "BrassPlus::TestAdd" << std::endl;
}

void BrassPlusPlus::TestVirtualAdd()
{
    std::cout << "BrassPlus::TestVirtualAdd" << std::endl;
}

BrassPlusPlus::~BrassPlusPlus()
{
    std::cout << "BrassPlusPlus::~BrassPlusPlus: " << (int64_t)this << std::endl;
}

BrassMinus.h

//
//  BrassMinus.h
//  TestC++11
//
//  Created by sai on 9/16/19.
//  Copyright (c) 2019 sai. All rights reserved.
//

#ifndef __TestC__11__BrassMinus__
#define __TestC__11__BrassMinus__

#include <iostream>

#include "Brass.h"

class BrassMinus: public Brass
{
public:
    void TestAdd(){}
    void TestVirtualAdd(){}
};


#endif /* defined(__TestC__11__BrassMinus__) */

输出

b can cast to bp: 0 is: 9BrassPlus
addressValue: 4303374608
b can't cast to bp: 1 is: 5Brass
*b can't cast to bpr: 1 is: 5Brass
addressValue: 4303374624
b can cast to bp: 2 is: 13BrassPlusPlus
addressValue: 4303374640
b can't cast to bp: 3 is: 10BrassMinus
*b can't cast to bpr: 3 is: 10BrassMinus
addressValue: 4303374656
3:1
3:1
4:1

参考

15.5 类型转换操作符 << C++ Primer Plus >> 第五版

使用dynamic_cast 强制转换的优点


转载:https://blog.csdn.net/infoworld/article/details/100896292
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场