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( )函数中,我们的返回值是一个类型,但是对于编译器而言,这个类型依赖类型参数KeyTypeValueType,所以编译器会认为这是变量或者数值。正确的做法如下:

typename Set< Pair<KeyType, ValueType> >::iterator begin( )
{ ... }

使用typename后,其后的字符串将会被解释为类型而非变量或数值。typename常用于多个类间的互相调用,以避免编译器的多义性。typenametypedef常常搭配使用,以简化代码,比如下面内容用到如下代码:

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( ) constconst_iterator end( ) const。而Set< Pair<KeyType, ValueType> >::iterator表明调用非const函数,所以出现错误。在const函数中调用非const函数或者变量可以使用const_cast,它可以解除常量性的限制。const_cast是类型转换运算符,虽然看上去像是函数,它的语法如下:

const_cast <typeName> ( expression );

typeNameexpression除了const性以外,其它类型是相同的,如const intint的区别。此外它们都必须是指针或引用。因此上述代码修改为:

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> >*,所以它是指针类型,符合要求。

posted @ 2025-08-24 05:34  永恒圣剑  阅读(8)  评论(0)    收藏  举报