成员函数与const
对于不改变类内部成员的成员函数,我们都要在函数后面加上const,对于会改变数据成员的函数则不加const。对成员函数加上const有明确的限制行为:调用该成员函数不会改变内部数据成员。但是,如果const函数的返回值是引用或指针呢?这种情况到底要不要对返回值加上const呢?先来看一段示例:
代码示例与结果
#include <iostream> using namespace std; struct Node { Node* next; int value; Node() : next(0), value(0){ } }; class TestList { typedef Node* node_ptr; typedef const Node* const_node_ptr; private: node_ptr header; public: TestList() : header(0){ } TestList(node_ptr n) : header(n){ } void print() const { node_ptr tmp = header; while (tmp != 0){ cout << tmp->value << (tmp->next == 0 ? "" : ", next: "); tmp = tmp->next; } cout << endl; } void setHeader(node_ptr n) { header = n; } node_ptr getHeaderPtr() const { return header; } node_ptr& getHeaderRef() const { return (node_ptr&)header; } }; int main(int argc, char** argv){ Node header; header.value = 1; TestList tl(&header); // tl.setHeader(&header); cout << "tl ori: " << endl; tl.print(); Node* nptr = tl.getHeaderPtr(); nptr->value = 2; cout << "tl node value can modify by pointer: " << endl; tl.print(); Node refNode; refNode.value = 3; refNode.next = &header; tl.getHeaderRef() = &refNode; cout << "tl node can modify by reference: " << endl; tl.print(); cout << "---------------------- const object ----------" << endl; const TestList ctl(&header); //tl.setHeader(&header); cout << "ctl ori: " << endl; ctl.print(); nptr = ctl.getHeaderPtr(); nptr->value = 5; cout << "ctl node value can modify by pointer: " << endl; ctl.print(); Node crefNode; crefNode.value = 6; crefNode.next = &header; ctl.getHeaderRef() = &crefNode; cout << "ctl node can modify by reference: " << endl; ctl.print(); }
上面示例代码的输出结果:
tl ori: 1 tl node value can modify by pointer: 2 tl node can modify by reference: 3, next: 2 ---------------------- const object ---------- ctl ori: 2 ctl node value can modify by pointer: 5 ctl node can modify by reference: 6, next: 5
由以上输出可以看到,通过修改const成员函数返回的引用或指针可以修改对象内部的值。这与const函数只能读取内部数据成员(加mutable的数据成员不包括在内)是否相矛盾呢?const函数本身是不会修改数据成员的,但是通过它的返回值可以在外部修改对象内部数据。如果对象是non-const的,这种情况还可以接受;但是如果对象是const的,这种情况就不是所期望的了。
个人建议
要防止这种情况发生可以对返回值加const,或者对于在类内部需要把返回值作为左值的则把访问级别限制为public以下(需要再外部修改数据成员的,则提供修改器)。如:
const_node_ptr getHeaderPtr() const { return header; } const node_ptr& getHeaderRef() const { return (node_ptr&)header; }
或
protected: node_ptr getHeaderPtr() const { return header; } node_ptr& getHeaderRef() const { return (node_ptr&)header; }
当然,对于在成员函数内部通过指针修改数据的就只能自己注意了。
相关推荐
C++中const用法总结.doc C++中const用法总结.doc 1. const修饰普通变量和指针 2. const修饰函数参数 3. const 修饰函数返回值 4. const修饰类对象/对象...6. const修饰成员函数 7. const常量与define宏定义的区别
3.常量成员函数 常量函数里的const是用来修饰*this的,其形式如下: int f() const{```} 然后这里就有意思了 *this的默认类型是type *const this,this指针有一个顶层const,但并没有底层const,由于低层const的...
2.常量成员函数,形式:type funname(type1 arg1,type2 arg2,…) const 1)常量成员函数,不能修改类数据成员,不能调用非常量函数。 2)常量成员函数的作用,可以有效的将类的函数分为可以修改类的函数,和不能修改...
05-易犯错误模型-为什么需要成员函数(补充资料)-传智扫地僧 06_课堂答疑类中写成员函数_调用的时才会执行 07_程序设计方法发展历程 08_C语言和C++语言的关系_工作经验分享 09_namespace和iotream 10_实用性加强_...
6.9 const成员函数 6.10构造函数 6.11默认构造函数 6.12析构函数 6.13析构对象数组 6.14总结 第7章 循环语句 7.1 循环语句的前身——goto语句 7.2 慎用goto语句 7.3 while语句 7.3.1 带运算符的while语句 7.3.2 以...
6.9 const成员函数 6.10构造函数 6.11默认构造函数 6.12析构函数 6.13析构对象数组 6.14总结 第7章 循环语句 7.1 循环语句的前身——goto语句 7.2 慎用goto语句 7.3 while语句 7.3.1 带运算符的while语句...
除非不可避免,如要调用malloc()函数时要用的void型指针转换成指定类型指针。 四、标准输入输出流 在C语言中,输入输出是使用语句scanf()和printf()来实现的,而C++中是使用类来实现的。 #include iostream.h ...
我们可以把类模板看做成⼀个函数 QSharedPointer为函数名, template中类型列表的为函数形参列表,typedef 为返回值。 T最终 的类型确认待你使⽤时由编译器实例化模板时才能推导出),QSharedPointer类模板分别重...
1 介绍 LuaBind 是一个帮助你绑定C++和Lua的库....引用或常量引用作为函数的第一个参数.该函数的剩下的参数将在Lua侧可见,而对象指针将被赋值给第一个 参数.如果我们有如下的C++代码: struct A { int ...
条款30: 避免这样的成员函数:其返回值是指向成员的非const指针或引用,但成员的访问级比这个函数要低 条款31: 千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针的引 条款32: 尽可能地推迟变量的...
谭浩强教授,我国著名计算机教育专家。1934年生。1958年清华大学毕业。学生时代曾担任清华大学学生会主席、北京市人民代表。他是我国计算机普及和高校...8.3.4 成员函数的存储方式 8.4 对象成员的引用 8.4.1 通过对象名...
条款30:避免这样的成员函数,其返回值是指向成员的非CONST指针或引用 条款31:千万不要返回局部对象的引用,也不要返回函数内部用NEW初始化的指针 条款32:尽可能推迟变量的定义 条款33:明智的使用INLINE 条款34:将...
(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调...
谭浩强教授,我国著名计算机教育专家。1934年生。1958年清华大学毕业。学生时代曾担任清华大学学生会主席、北京市人民代表。他是我国计算机普及和高校...8.3.4 成员函数的存储方式 8.4 对象成员的引用 8.4.1 通过对象名...
7.4.3 const对象和成员函数 7.4.4 只读存储能力 7.5 可变的(volatile) 7.6 小结 7.7 练习 第8章 内联函数 8.1 预处理器的缺陷 8.2 内联函数 8.2.1 类内部的内联函数 8.2.2 存取函数 8.3 内联函数和编译器 ...
1.string类成员函数c_str()的原型: const char *c_str()const;//返回一个以null终止的c字符串 2.c_str()函数返回一个指向正规c字符串的指针,内容和string类的本身对象是一样的,通过string类的c_str()函数能够把...
05-易犯错误模型-为什么需要成员函数(补充资料)-传智扫地僧 06_课堂答疑类中写成员函数_调用的时才会执行 07_程序设计方法发展历程 08_C语言和C++语言的关系_工作经验分享 09_namespace和iotream 10_实用性加强_...
相当经典的教程,这次的上传一共5集,5分,相当于每1集要1分下载. 本课程是C++ Primer初级教程,课程内容是学习C++语言基础知识,对应着教材的第1章到第8章。 第1章 快速入门 1.1 编写简单的C++程序 1.2 初窥...
8.2 成员函数的重载、覆盖与隐藏 60 8.3 参数的缺省值 63 8.4 运算符重载 64 8.5 函数内联 65 8.6 一些心得体会 68 第9章 类的构造函数、析构函数与赋值函数 69 9.1 构造函数与析构函数的起源 69 9.2 构造函数的初始...