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. Kafka丢失数据问题优化总结

    数据丢失是一件非常严重的事情事,针对数据丢失的问题我们需要有明确的思路来确定问题所在,针对这段时间的总结,我个人面对kafka 数据丢失问题的解决思路如下: 是否真正的存在数据丢失问题,比如有很多时候 ...

  2. Parallel Decision Tree

    Decision Tree such as C4.5 is easy to parallel. Following is an example. This is a non-parallel vers ...

  3. Windows Server 2008 R2(X64) MSDN镜像简体中文版与英文版ISO下载及Key激活码

    Windows Server 2008 R2 MSDN ISO镜像简体中文版 文件名:cn_windows_server_2008_r2_standard_enterprise_datacenter_ ...

  4. java基础知识 构造方法

    在java里面,构造方法也就是构造函数 构造函数=构造方法;构造方法是一种特殊的方法,具有以下特点.(1)构造方法的方法名必须与类名相同.(2)构造方法没有返回类型,也不能定义为void,在方法名前面 ...

  5. SpringData关键字查询练习

    我们在上一节知道SpringData关键字有很多,我就拿几个例子练练手 1.需求我们查询lastName like sun and id < ?的查询 package com.fxr.sprin ...

  6. mysql索引之主键索引

    MySQL目前主要有以下几种索引类型:1.普通索引2.唯一索引3.主键索引4.组合索引5.全文索引 二.语句 CREATE TABLE table_name[col_name data type] [ ...

  7. 53. Maximum Subarray(动态规划 求最大子数组)

      Find the contiguous subarray within an array (containing at least one number) which has the larges ...

  8. python uwsgi报错epoll_ctl(): Bad file descriptor

    今天安装了uwsgi+supervisord+nginx,一直访问不了 直接启动uwsgi使用nginx访问,查看有大量报错:epoll_ctl(): Bad file descriptor [cor ...

  9. Python的星号(*)和双星号(**)用法

    ①引言 在Python中,星号除了用于乘法数值运算和幂运算外,还有一种特殊的用法是在变量前加单个星号或两个星号,实现多参数的传人或变量的拆解. ②什么是星号变量 最初,星号变量是用在函数的参数传递上的 ...

  10. tomcat jdbc pool

    文中内容主要转自:http://www.open-open.com/lib/view/open1327478028639.html http://www.open-open.com/lib/view/ ...