c++有时候需要为类的某个成员函数重载常量与非常量的版本,定义常量版本是为了保证该函数可作用于常量类对象上,并防止函数改动对象内容。但有时两个版本的函数仅仅是在返回的类型不同,而在返回前做了大量相同的工作,那么代码会有大量重复,由此也会带来编译时间和代码膨胀等开销。例如下面的类成员函数:

 #include <string>

 class Test
{
using size_type = std::string::size_type;
public:
const char & operator[](size_type index) const;
char & operator[](size_type index);
private:
std::string str;
}; const char & Test::operator[](size_type index) const
{
//...
//...
//要执行的操作
return str[index];
} char & Test::operator[](size_type index)
{
//...
//...
//要执行的操作
return str[index];
}

  虽然完全可以将执行的相同的动作写在一个新的成员函数里并将其定义为私有的,但这样仍然有函数调用和返回值的重复。一种可行的方法是让两个函数的其中一个调用另一个,如下所示:

 class Test
{
using size_type = std::string::size_type;
public:
const char & operator[](size_type index) const;
char & operator[](size_type index);
private:
std::string str;
}; const char & Test::operator[](size_type index) const
{
//...
//...
//要执行的操作
return str[index];
} char & Test::operator[](size_type index)
{
return const_cast<char &>(static_cast<const Test &>(*this)[index]);
}

  非常量版本调用了常量版本,在这过程中进行了两次转型:

    ①static_cast<const Test &>(*this),将非常量类型的Test对象转换成常量类型(const)的Test对象,即把<Test &>类型的*this转换成<const Test &>类型,再调用常量版本的下标运算符。若没有进行转换直接调用下标运算符,等于函数递归调用自己,将会进入死循环。

    ②const_cast<char &>(),上一步的static_cast<const Test &>(*this)[index]调用了常量版本的下标运算符,返回的类型为const char &,接下来便利用const_cast去除返回值的const属性。

  附注1:

  应该注意函数调用的主宾关系:非常量版本调用常量版本并进行类型转换。反过来的做法则是一种错误的行为,常量版本成员函数不会改变对象的逻辑状态,而在常量版本中调用非常量版本则存在着可能改变对象的风险。实际上这样的代码若要通过编译,需要用const_cast去除*this的const属性,这显然是一种不安全的行为。相反,非常量版本成员函数本来就可以改动对象,因为在函数内部调用常量版本并不会有风险。

  

c++类成员函数重载常量与非常量版本时避免代码重复的一种方法的更多相关文章

  1. 直接调用类成员函数地址(用汇编取类成员函数的地址,各VS版本还有所不同)

    在C++中,成员函数的指针是个比较特殊的东西.对普通的函数指针来说,可以视为一个地址,在需要的时候可以任意转换并直接调用.但对成员函数来说,常规类型转换是通不过编译的,调用的时候也必须采用特殊的语法. ...

  2. C++之static类成员,static类成员函数

    0.static修饰类中成员,表示类的共享数据 1.static类成员 在C++primer里面说过,static类成员不像普通的类数据成员,static类数据成员独立于一切类对象处在.static类 ...

  3. 并发编程: c++11 thread(Func, Args...)利用类成员函数创建线程

    c++11是VS2012后支持的新标准,为并发编程提供了方便的std::thread. 使用示例: #include <thread> void thread_func(int arg1, ...

  4. C++ 面向对象 类成员函数this指针

    每个类成员函数都只涉及一个对象, 即调用它的对象. 但有时候方法可能涉及到两个对象, 在这种情况下需要使用C++ 的 this 指针 假设将方法命名为topval(), 则函数调用stock1.top ...

  5. 【非原创】C++类成员函数的重载、覆盖和隐藏

    链接:https://www.nowcoder.com/questionTerminal/266d3a6d4f1b436aabf1eff3156fed95来源:牛客网 题目:类成员函数的重载.覆盖和隐 ...

  6. 重载运算符:类成员函数or友元函数

    类成员函数: bool operator ==(const point &a)const { return x==a.x; } 友元函数: friend bool operator ==(co ...

  7. C++类成员函数的重载、覆盖和隐藏区别?

    C++类成员函数的重载.覆盖和隐藏区别? a.成员函数被重载的特征:(1)相同的范围(在同一个类中):(2)函数名字相同:(3)参数不同:(4)virtual 关键字可有可无.b.覆盖是指派生类函数覆 ...

  8. C++:类成员函数的重载、覆盖和隐藏区别?

    #include <iostream> class A { public: void func() { std::cout << "Hello" <& ...

  9. 类成员函数的重载、覆盖和隐藏区别 (C++)(转)

    类成员函数的重载.覆盖和隐藏区别 (C++)   这是本人第一次写博客,主要是想记录自己的学习过程.心得体会,一是可以方便以后回顾相关知识,二是可以与大家相互学习交流. 关于C++中类成员函数的重载. ...

随机推荐

  1. 005-java的Annotation

    一.概述 Annotation,JDK1.5开始提供 二.基本定义 public @interface HelloWorld { } 1.使用@Interface定义,名称大写 2.使用@Target ...

  2. Atom飞行手册翻译

    https://www.w3cschool.cn/atomflightmanualzhcn/

  3. Spark Shuffle(一)ShuffleWrite:Executor如何将Shuffle的结果进行归并写到数据文件中去(转载)

    转载自:https://blog.csdn.net/raintungli/article/details/70807376 当Executor进行reduce运算的时候,生成运算结果的临时Shuffl ...

  4. Django REST framework 之 API认证

    RESTful API 认证 和 Web 应用不同,RESTful APIs 通常是无状态的, 也就意味着不应使用 sessions 或 cookies, 因此每个请求应附带某种授权凭证,因为用户授权 ...

  5. gitlab卸载

    1.停止gitlab gitlab-ctl stop 2.卸载gitlab(注意这里写的是gitlab-ce) rpm -e gitlab-ce 3.查看gitlab进程 ps aux | grep ...

  6. 找回 linux root密码的几种方法

    第1种方法: 1.在系统进入单用户状态,直接用passwd root去更改  2.用安装光盘引导系统,进行linux rescue状态,将原来/分区挂接上来,作法如下: Java代码  #> c ...

  7. Java游戏服务器成长之路——你好,Mongo

    关于mongo的思考 第一阶段的弱联网游戏已基本完成,截至今天下午,测试也基本差不多了,前端还有一些小bug需要优化,接下来会接入小米,360,百度,腾讯等平台,然后推广一波,年前公司还能赚一笔,而我 ...

  8. ACM-ICPC 2018 沈阳赛区网络预赛 Solution

    A. Gudako and Ritsuka 留坑. B. Call of Accepted 题意:定义了一种新的运算符$x d y$ 然后给出中缀表达式,求值 思路:先中缀转后缀,然后考虑如何最大如何 ...

  9. Entity Framework 数据生成选项DatabaseGenerated(转)

    在EF中,我们建立数据模型的时候,可以给属性配置数据生成选项DatabaseGenerated,它后有三个枚举值:Identity.None和Computed. Identity:自增长 None:不 ...

  10. SecureCRT 会话空闲时超时退出处理

    参考文章:http://www.cnblogs.com/xuxm2007/archive/2011/04/21/2023611.html http://yunwei.blog.51cto.com/38 ...