场景
C++
提供了哪四种类型转换的操作符? 它们分别用在那种情况下?
说明
-
C++
提供的四种类型转换操作符是dynamic_cast
,static_cast
,const_cast
,reinterpret_cast
. -
以下用例子说明它的使用场景.
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 >> 第五版
转载:https://blog.csdn.net/infoworld/article/details/100896292
查看评论