快捷搜索:   服务器  安全  linux 安全  MYSQL  dedecms

EffectiveC++2eItem21(2)

    类C的一个成员函数中,this指针就好象经过如下的声明:

    C * const this;              // 非const成员函数中

    const C * const this;        // const成员函数中

    这种情况下(即编译器不支持mutable的情况下),如果想使那个有问题的String::length版本对const和非const对象都合法,就只有把this的类型从const C * const改成C * const。不能直接这么做,但可以通过初始化一个局部变量指针,使之指向this所指的同一个对象来间接实现。然后,就可以通过这个局部指针来访问你想修改的成员:

    size_t String::length() const
    {
      // 定义一个不指向const对象的
      // 局部版本的this指针
      String * const localThis =
        const_cast<String * const>(this);

      if (!lengthIsValid) {
        localThis->dataLength = strlen(data);
        localThis->lengthIsValid = true;
      }

      return dataLength;
    }

    做的不是很漂亮。但为了完成想要的功能也就只有这么做。

    当然,如果不能保证这个方法一定可行,就不要这么做:比如,一些老的“消除const”的方法就不行。特别是,如果this所指的对象真的是const,即,在定义时被声明为const,那么,“消除const”就会导致不可确定的后果。所以,如果想在成员函数中通过转换消除const,就最好先确信你要转换的对象最初没有被定义为const。

    还有一种情况下,通过类型转换消除const会既有用又安全。这就是:将一个const对象传递到一个取非const参数的函数中,同时你又知道参数不会在函数内部被修改的情况时。第二个条件很重要,因为对一个只会被读的对象(不会被写)消除const永远是安全的,即使那个对象最初曾被定义为const。

    例如,已经知道有些库不正确地声明了象下面这样的strlen函数:

    size_t strlen(char *s);

    strlen当然不会去修改s所指的数据——至少我一辈子没看见过。但因为有了这个声明,对一个const char *类型的指针调用这个函数时就会不合法。为解决这个问题,可以在给strlen传参数时安全地把这个指针的const强制转换掉:

    const char *klingonGreeting = "nuqneH"; // "nuqneH"即"Hello"
                                            //
    size_t length =
      strlen(const_cast<char*>(klingonGreeting));

    但不要滥用这个方法。只有在被调用的函数(比如本例中的strlen)不会修改它的参数所指的数据时,才能保证它可以正常工作。

顶(0)
踩(0)

您可能还会对下面的文章感兴趣:

最新评论