关键字const(2)--const与重载

所谓重载,是指允许存在多个同名函数,而这些函数的参数表不同,即函数名相同但函数的签名不同。重载并不是面向对象编程的特有属性,这是因为重载是在编译阶段实现的,编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数。

关于const 重载,在《C++ primer》一书中这样描述:

可基于函数的引用形参是指向 const 对象还是指向非 const 对象,实现函数重载。将引用形参定义为 const 来重载函数是合法的,因为编译器可以根据实参是否为 const 确定调用哪一个函数。

const到底是不是一个重载的参考对象,请看下面的例子

class A
{
public:
    void f(int i){ std::cout<<"1";}; //函数1
    void f(int i) const { std::cout<<"2" ;};//函数2

};

这个地方的重载是没有问题的,说明const 修饰函数能够区分重载

class B
{
   void f(int i);
   const void f(int i);

};

这次编译器会报出 'B::f' : redefinition; 的错误,说明const作为修饰返回值不能够区分重载

class C
{
    void f(int i);
    void f(const  int i);
};

这个是错误的,编译通不过。那么是不是说明内部参数的const不予重载呢?
再看下面的例子:

class D
{
public:
    void f(int &i) { std::cout<<"3";}; //函数3;
    void f(const  int &i){ std::cout<<"4" ;};//函数4
};

这个程序是正确的,看来上面的结论是错误的。为什么会这样呢?函数按值传递是通过复制实参创建一个临时变量传递进函数的,所以这个时候无论加不加const对实参都不会产生影响,在这种情况下进行重载是没有意义的,所以规定不能重载。但是当按指针或引用传参时,函数内部就可能会改变实参,这时const才会起作用,重载就是有意义的,所以规定可以重载。

另外返回值不能作为区分重载的条件。

现在来看一下成员 函数调用的情况:

A a;
a.f(1);

对于以上调用,如果函数1不存在就会调用函数2,如果函数1和函数2都存在,优先调用函数1.

const A a;
a.f(1);```
却只能调用函数2,如果函数2不存在,将会报错。

int i = 0;
D d;
d.f(i);```
以上调用既可以调用函数3也可以调用函数4,优先调用函数3.

const int i = 0;
D d;
d.f(i);```
只能调用函数4,函数3存在函数4不存在,也不能调用函数3,直接报错

**总结**: 
- const 对象只能调用const 方法,非const 对象既能调用const 方法也能调用非const方法,优先调用非const方法。
- const 变量 只能调用带有const 参数的方法,非const 变量既能调用带const 参数的方法,也能调用不带cosnt 参数的方法,优先调用不带const 参数的方法

-
-
-
 
######const对象调用const方法时要注意的一个坑

char& operator[](int posion) // function_1
{
return data[posion];
};

注意,这里该函数的返回值为一个引用,否则str[0] = 'c'这样的语句就会不合法,因为str[0]将是一个左值。
那么,是否提供这样一个function_1就足够了呢?看下面这段代码:
const String str= "She";
char c = str[0];    // 错误!编译提示:error C2678: 二进制“[” : 没有找到接受“const String”类型的左操作数的运算符(或没有可接受的转换)
很显然,我们必须还要为const String提供一个const版本的opeartor[]。如下:

char& operator[](int posion) const
{
return data[posion];
}

这样,当使用const的String对象使用[]操作符时,便会调用该const的重载版本。
但是,这样就OK了嘛?虽然上面的那段代码没有问题了,但是其中却隐藏了一个陷阱,看如下代码:

const String str = "She";
str[0] = 'T';

上面这段代码可以编译,运行通过,str变为了"The"!而str声明为const的!!
现在,你应该知道了,对于const的该操作符重载函数其返回值也应该是const的,否则就会出现可以通过其修改const对象的漏洞。修改如下:

const char& operator[](int posion) const
{
return data[posion];
}

好了,现在没有问题了!
我们再回过头来看一下,为了给String提供一个[]操作符来读写指定位置的字符,需要提供如下两个函数,以分别对非const String对象和const String对象提供支持:

char& operator[](int posion)
{
return data[posion];
};
const char& operator[](int posion) const
{
return data[posion];
}



参考文章:
http://blog.csdn.net/pizi0475/article/details/46867199
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 13,152评论 1 51
  • C++运算符重载-下篇 本章内容:1. 运算符重载的概述2. 重载算术运算符3. 重载按位运算符和二元逻辑运算符4...
    Haley_2013阅读 5,320评论 0 49
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 32,456评论 18 399
  • 小杨老师是学校新分来的老师,长着一双眯眯眼,说话时脑袋上扬,似乎是在和找他说话的人究竟站在哪个方向。 小杨老师和我...
    简儿的十年阅读 2,939评论 25 20
  • 今天凌晨结束的一场足总杯1/4决赛中,阿森纳5-0大胜林肯城成功晋级4强,主帅温格出席了赛后新闻发布会。 关于对手...
    风吹雨成花呀阅读 1,580评论 0 0

友情链接更多精彩内容