effective_在none-const和const成员函数中避免重复

1.static_cast

用法:static_cast < type-id > ( expression )
该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查(动态绑定),所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成float、non-const对象转换为const对象等是安全的。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
1、C++中的static_cast执行非多态的转换,用于代替C中通常的转换操作。因此,被做为显式类型转换使用。比如:

int i = 65;
char j = static_cast<char>(i);
cout << j << endl;//结果为A
int i=2;
float j = static_cast<float>(i);

int型的2和float型的2,在内存中是由不同的二进制序列表示的。不过在执行static_cast<float>(i)这一操作时,编译器会生成目标代码,将i的整型二进制表示转为i的浮点型二进制表示,这种叫做基于内容的转换,安全。

但是,static_cast也并非绝对安全,这是因为有void指针的存在。任何类型的指针都可以隐含地转换为void指针。如:

int i=2;
void *vp=&i;

这两句话本身没有安全性问题,因为void指针在语义上就是所指向对象的内容的数据类型不确定的指针,因此它可以指向任何类型的对象。但是,通过void指针不能对它所指向的对象进行任何操作,在执行操作之前,还需将void指针转换为具体类型的指针。C++不允许void指针到具体类型指针的转换隐含地发生,这种转换需要显式地进行,用static_cast即可。

int i = 2;
void *vp = &i;
int *p = static_cast<int*>(vp);//安全的
cout << *p << endl;

上面的例子如果将void类型转换为指针原来的类型(int*),那么是安全的,否则仍然是不安全的。
如:float *p = static_cast<float*>(vp);不安全。

2.reinterpret_cast

C++中的reinterpret_cast主要是将数据从一种类型的转换为另一种类型。所谓“通常为操作数的位模式提供较低层的重新解释”也就是说将数据以二进制存在形式的重新解释。比如:

float i = 1.;
float *p = &i;
int j = reinterpret_cast<int>(p);//将指针p的值以二进制(位模式)的方式被解释为整型,并赋给i
cout << p << endl;
cout << j << endl;

此时结果,j与p的值是完全相同的。reinterpret_cast的作用是说将指针p的值以二进制(位模式)的方式被解释为整型,并赋给j,一个明显的现象是在转换前后没有数位损失。

再看另一个例子:

int i=2;
float*p=reinterpret_cast<float*>(&i);
cout<<p<<endl;
cout<<&i<<endl;//两句结果相同

这里把int类型的&i转化为float类型,这个转换是怎么进行的呢?无论是int类型的指针还是float类型的指针,存储的都是同一个地址,只是地址中的数据被解释被解释成不同类型而已。这种转换的结果就是,p作为浮点型指针,却指向了整型变量i,所以通过p访问整型变量i,肯定是有问题的,即*p的结果一定不为2.

3.const_cast

const_cast一般用于强制消除对象的常量性。它是唯一能做到这一点的C++风格的强制转型。这个转换能去除一个对象的const属性,它只能用于将常指针转换为普通指针,将常引用转换为普通引用

接下来就到了本文的核心点!!!

class Text {
public:
	const char& operator[](int pos)const
	{
		return text[pos];
	}
	char& operator[](int pos)
	{
		return text[pos];
	}

	Text(string s) :text(s) {}
private:
	string text;
};

上述代码operator[]函数重载了两个版本,但是这不是最佳的选择,最佳的办法是使用none-const版本调用const版本,避免代码重复。这就要用到const_cast.
优化后的代码如下:

#include<iostream>
#include<string>
using namespace std;
class Text {
public:
	const char& operator[](int pos)const
	{
		return text[pos];
	}
	char& operator[](int pos)//使用none-const版本调用const版本,避免代码重复
	{
		return const_cast<char&>  //把const char& operator[]函数返回的常引用的const属性去除
			(static_cast<const Text*>(this)->operator[](pos));//把this从原始类型Text*转换为const Text*,这样就可以调用常成员函数

		//return const_cast<char&>  //把const char& operator[]函数返回的常引用的const属性去除
		//	(static_cast<const Text&>(*this)[pos]);//把*this从原始类型Text&转换为const Text&,这样就可以调用常成员函数
	}

	Text(string s) :text(s) {}
	
private:
	string text;
};
int main() {
	Text s("abc");
	const Text cs("abc");
	cout << s[0] << endl;//使用none-const版本调用const版本,避免代码重复
	cout << cs[0] << endl;//直接调用const版本
	s[0] = 'x';
	
	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值