实验原因

说明如何使用const描述保护类数据不会意外修改.

编译环境

vc6sp6 + win7x64

工程下载

copyConstruction_constMemberFunction.zip

 

使用非const成员函数,引起的拷贝构造函数报错

  1. class CStudent
  2. {
  3. /// 常量定义
  4. public:
  5. enum {NAME_SIZE_MAX = 64};
  6. /// 构造, 拷贝构造, 析构函数
  7. public:
  8. CStudent();
  9. CStudent(const char* pcName, size_t nId = 1, int iAge = 20);
  10. CStudent(const CStudent& src);
  11. virtual ~CStudent();
  12. /// 成员函数
  13. public:
  14. void clear();
  15. private:
  16. void init(); ///< 类初始化
  17. void uninit(); ///< 类反初始化
  18. void copy(CStudent& src);
  19. /// setter, getter
  20. public:
  21. // m_nId
  22. void setter_m_nId(size_t nIn) {m_nId = nIn;}
  23. size_t getter_m_nId() {return m_nId;}
  24. // m_cName
  25. void setter_m_cName(const char* pcIn)
  26. {
  27. if (NULL == pcIn)
  28. return;
  29. memset(m_cName, '\0', NAME_SIZE_MAX);
  30. strncpy(m_cName, pcIn,
  31. (strlen(pcIn) < (NAME_SIZE_MAX - 1)) ?
  32. strlen(pcIn) : (NAME_SIZE_MAX - 1));
  33. }
  34. const char* getter_m_cName() {return m_cName;}
  35. // m_iAge
  36. void setter_m_iAge(int iIn) {m_iAge = iIn;}
  37. int getter_m_iAge() {return m_iAge;}
  38. /// 成员变量
  39. private:
  40. size_t m_nId; ///< 学号
  41. char m_cName[NAME_SIZE_MAX]; ///< 姓名
  42. int m_iAge; ///< 年龄
  43. };
  1. CStudent::CStudent(const CStudent& src)
  2. {
  3. copy(src);
  4. }
  5. void CStudent::copy(CStudent& src)
  6. {
  7. setter_m_cName(src.getter_m_cName());
  8. setter_m_nId(src.getter_m_nId());
  9. setter_m_iAge(src.getter_m_iAge());
  10. }

拷贝构造函数声明为(const class&), 但是拷贝构造函数调用了非const成员函数, 会报错

error C2664: 'copy' : cannot convert parameter 1 from 'const class CStudent' to 'class CStudent &'

如果要查报错资料资料, 查一下关键字.

error C2664: cannot convert parameter 1 from 'const class ' to 'class &'

需要将拷贝构造函数(直接, 简捷)调用的成员函数全部改成const成员函数,

需要将拷贝构造函数调用的成员函数入参为class& 或 class*全部改成 const class& 或 const class*

  1. class CStudent
  2. {
  3. /// 常量定义
  4. public:
  5. enum {NAME_SIZE_MAX = 64};
  6. /// 构造, 拷贝构造, 析构函数
  7. public:
  8. CStudent();
  9. CStudent(const char* pcName, size_t nId = 1, int iAge = 20);
  10. CStudent(const CStudent& src);
  11. CStudent(const CStudent* psrc);
  12. virtual ~CStudent();
  13. /// 成员函数
  14. public:
  15. void clear();
  16. private:
  17. void init(); ///< 类初始化
  18. void uninit(); ///< 类反初始化
  19. void copy(const CStudent* psrc);
  20. /// setter, getter
  21. public:
  22. // m_nId
  23. void setter_m_nId(size_t nIn) {m_nId = nIn;}
  24. size_t getter_m_nId() const {return m_nId;}
  25. // m_cName
  26. void setter_m_cName(const char* pcIn)
  27. {
  28. if (NULL == pcIn)
  29. return;
  30. memset(m_cName, '\0', NAME_SIZE_MAX);
  31. strncpy(m_cName, pcIn,
  32. (strlen(pcIn) < (NAME_SIZE_MAX - 1)) ?
  33. strlen(pcIn) : (NAME_SIZE_MAX - 1));
  34. }
  35. const char* getter_m_cName() const {return m_cName;}
  36. // m_iAge
  37. void setter_m_iAge(int iIn) {m_iAge = iIn;}
  38. int getter_m_iAge() const {return m_iAge;}
  39. /// 成员变量
  40. private:
  41. size_t m_nId; ///< 学号
  42. char m_cName[NAME_SIZE_MAX]; ///< 姓名
  43. int m_iAge; ///< 年龄
  44. };
  1. CStudent::CStudent(const CStudent& src) ///< 入参改成const class&
  2. {
  3. copy(&src);
  4. }
  5. CStudent::CStudent(const CStudent* psrc)
  6. {
  7. copy(psrc);
  8. }
  9. void CStudent::copy(const CStudent* psrc)
  10. {
  11. setter_m_cName(psrc->getter_m_cName());
  12. setter_m_nId(psrc->getter_m_nId());
  13. setter_m_iAge(psrc->getter_m_iAge());
  14. }

const 成员函数的含义

摘录自 <<C++ const详解>>

http://blog.csdn.net/zhuanshenweiliu/article/details/38223907

3. const成员函数
任何不会修改数据成员(即函数中的变量)的函数都应该声明为const类型。

如果在编写const成员函数时,不慎修改了数据成员,或者调用了其它非const成员函数,编译器将指出错误,这无疑会提高程序的健壮性。

以下程序中,类stack的成员函数GetCount仅用于计数,从逻辑上讲GetCount应当为const函数。编译器将指出GetCount函数中的错误。
class Stack
{
public:
void Push(int elem);
int Pop(void);
int GetCount(void) const; // const成员函数
private:
int m_num;
int m_data[100];
} ;
int Stack::GetCount(void) const
{
++ m_num; //编译错误,企图修改数据成员m_num
Pop(); //编译错误,企图调用非const函数
return m_num;
}
const 成员函数的声明看起来怪怪的:const 关键字只能放在函数声明的尾部,大概是因为其它地方都已经被占用了。
关于Const函数的几点规则:
a. const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数.
b. const对象的成员是不可修改的,然而const对象通过指针维护的对象却是可以修改的.
c. const成员函数不可以修改对象的数据,不管对象是否具有const性质.它在编译时,以是否修改成员数据为依据,进行检查.

http://blog.csdn.net/lostspeed/article/details/50291749

拷贝构造函数和const成员函数的更多相关文章

  1. C++类的const成员函数、默认的构造函数、复制形参调用函数(转)

    C++类的const成员函数 double Sales_item::avg_price() const { } const关键字表明这是一个const成员函数,它不可以修改Sales_item类的成员 ...

  2. 12.C++-构造函数与析构函数调用顺序,const成员函数,const对象

    单个对象创建时,构造函数的调用顺序 1.首先判断该对象的类是否拥有父类,若有则先调用父类的构造函数 2.判断该对象的成员是否是其它类的成员,若是则调用成员变量的构造函数(调用顺序和声明顺序相同) 3. ...

  3. 【C++】拷贝构造函数和赋值符函数

    在C++中,调用拷贝构造函数有三种情况: 1.一个对象作为函数参数,以值传递的方式传入函数体. 2.一个对象作为函数返回值,以值传递的方式从函数返回. 3.一个对象用于给另外一个对象进行初始化(复制初 ...

  4. c++ 学习之const专题之const成员函数

    一些成员函数改变对象,一些成员函数不改变对象. 例如: int Point::GetY() { return yVal; } 这个函数被调用时,不改变Point对象,而下面的函数改变Point对象: ...

  5. C++ Const成员函数

    一些成员函数改变对象,一些成员函数不改变对象. 例如:  int Point::GetY() { return yVal; }  这个函数被调用时,不改变Point对象,而下面的函数改变Point对象 ...

  6. c++中的const参数,const变量,const指针,const对象,以及const成员函数

    const 是constant 的缩写,“恒定不变”的意思.被const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性.所以很多C++程序设计书籍建议:“Use const whe ...

  7. (转)函数后面加const--C++ const成员函数

    类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变. 在设计类的时候,一个原则就是对于不改变数据成员的成员函数都要在后面加 const,而对于 ...

  8. 类1(this指针/const成员函数/类作用域/外部成员函数/返回this对象的函数)

    假设我们要设计一个包含以下操作的 Sales_data 类: 1.一个 isbn 成员函数,用于返回对象的 book_no 成员变量 2.一个 combine 成员函数,用于将一个 Sales_dat ...

  9. const成员函数

    尽管函数名和参数列表都相同,void foo( ) const成员函数是可以与void foo( )并存的,可以形成重载! 我们假设调用语句为obj.foo(),如果obj为non-const对象,则 ...

随机推荐

  1. Objective-C基础教程读书笔记(6)

    第6章 源文件组织 到目前为止,我们讨论过的所有项目都是把源代码统统放入main.m文件中.类的main()函数,@interface和@implementation部分都被塞入同一个文件里.这种结构 ...

  2. Linux编程---I/O部分

    非常多函数都能够在网上找到,也比較基础,所以原型仅仅给出了函数名.详细用到再man吧. 输入输出是个非常重要的一块内容.差点儿网络相关的东西基本都是靠底层IO调用来实现的. 好吧.还是先踏踏实实的介绍 ...

  3. sizeof,终极无惑(上)

    0. 前向声明 sizeof,一个其貌不扬的家伙,引无数菜鸟竟折腰,小虾我当初也没少犯迷糊,秉着“辛苦我一个,幸福千万人”的伟大思想,我决定将其尽可能具体的总结一下. 但当我总结的时候才发现,这个问题 ...

  4. Codeforces 360C Levko and Strings dp

    题目链接:点击打开链接 题意: 给定长度为n的字符串s,常数k 显然s的子串一共同拥有 n(n-1)/2 个 要求找到一个长度为n的字符串t,使得t相应位置的k个子串字典序>s #include ...

  5. sqlserver 分页查询总结

    sqlserver2008不支持关键字limit ,所以它的分页sql查询语句将不能用mysql的方式进行,幸好sqlserver2008提供了top,rownumber等关键字,这样就能通过这几个关 ...

  6. xcode生成的IOS安装文件的位置

    通过xcode生成可以在IOS系统下运行的文件的具体设置: 1.首先,需要有相应的程序,并且在mac下的xcode编译后,能够在模拟器中完美运行. 2.单击xcode,打开Xcode > Pre ...

  7. Scriptcase在线试用开发环境

    现在,你可以通过浏览器在线试用的方式,体验Scriptcase的高效快速开发方式. 只需要有上网环境就可以使用: 兼容几乎所有的浏览器(IE.Firefox.Chrome.Opera……): 客户端无 ...

  8. zabbix 添加主机成功失败判断

    zabbix 成功添加后: $VAR1 = bless( { 'version' => 0, 'content' => { 'jsonrpc' => '2.0', 'id' => ...

  9. 基于visual Studio2013解决算法导论之017查找第n小元素

     题目 查找第n小元素 解决代码及点评 #include <stdio.h> #include <stdlib.h> #include <malloc.h> ...

  10. 一步一步重写 CodeIgniter 框架 (5) —— 实现Controller,并加载Model

    CodeIgniter 框架采用MVC模式,而MVC模式中起纽带作用的就是C(控制器),在控制器的中通过加载模型获得数据,将数据传到视图中进行展示.本课将实现在控制器中加载模型. 1. 控制器的实现 ...