C++ 小结之typename与const_cast
编译器类型强调
typename的一个重要作用就是强调类型与变量的区别。如下代码:
template <typename KeyType, typename ValueType>
class Map
{
private:
template <typename KeyType_, typename ValueType_>
class Pair
{
...
};
Set< Pair<KeyType, ValueType> > map;
public:
// 错误
Set< Pair<KeyType, ValueType> >::iterator begin( )
{ ... }
...
};
template <typename Object>
class Set
{
...
};
在begin( )函数中,我们的返回值是一个类型,但是对于编译器而言,这个类型依赖类型参数KeyType与ValueType,所以编译器会认为这是变量或者数值。正确的做法如下:
typename Set< Pair<KeyType, ValueType> >::iterator begin( )
{ ... }
使用typename后,其后的字符串将会被解释为类型而非变量或数值。typename常用于多个类间的互相调用,以避免编译器的多义性。typename与typedef常常搭配使用,以简化代码,比如下面内容用到如下代码:
typedef typename Set< Pair<KeyType, ValueType> >::iterator iterator;
这样一个很长的类型就可以简单表示。
const_cast 去常量性
const函数默认其内调用的变量或方法都是const性,以达到常量性从而避免修改类的数据。考虑如下代码:
template <typename KeyType, typename ValueType>
class Map
{
private:
Set< Pair<KeyType, ValueType> > map;
...
public:
typename Set< Pair<KeyType, ValueType> >::iterator find( const KeyType & key ) const
{
typedef typename Set< Pair<KeyType, ValueType> >::iterator iterator;
typedef Set< Pair<KeyType, ValueType> > Set;
for( iterator itr = map.begin( ); itr != map.end( ); ++itr ) // 错误
...
...
}
...
};
template <typename Object>
class Set
{
public:
iterator begin( );
const_iterator begin( ) const;
iterator end( );
const_iterator end( ) const;
...
};
在const函数中会默认调用const方法,所以map.begin( )与map.end( )分别是const_iterator begin( ) const与const_iterator end( ) const。而Set< Pair<KeyType, ValueType> >::iterator表明调用非const函数,所以出现错误。在const函数中调用非const函数或者变量可以使用const_cast,它可以解除常量性的限制。const_cast是类型转换运算符,虽然看上去像是函数,它的语法如下:
const_cast <typeName> ( expression );
typeName与expression除了const性以外,其它类型是相同的,如const int与int的区别。此外它们都必须是指针或引用。因此上述代码修改为:
typename Set< Pair<KeyType, ValueType> >::iterator find( const KeyType & key ) const
{
typedef typename Set< Pair<KeyType, ValueType> >::iterator iterator;
typedef Set< Pair<KeyType, ValueType> > Set;
for( iterator itr = const_cast<Set*>(&map)->begin( ); itr != const_cast<Set*>(&map)->end( ); ++itr )
...
...
}
&map是取map的地址,它的地址类型是Set< Pair<KeyType, ValueType> >*,所以它是指针类型,符合要求。
浙公网安备 33010602011771号