拷贝构造函数和const成员函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拷贝构造函数和const成员函数相关的知识,希望对你有一定的参考价值。

实验原因

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

编译环境

vc6sp6 + win7x64

工程下载

        copyConstruction_constMemberFunction.zip

 

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

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

 

 

[cpp] view plain copy
 
  1. CStudent::CStudent(const CStudent& src)  
  2. {  
  3.     copy(src);  
  4. }  
  5.   
  6. void CStudent::copy(CStudent& src)  
  7. {  
  8.     setter_m_cName(src.getter_m_cName());  
  9.     setter_m_nId(src.getter_m_nId());  
  10.     setter_m_iAge(src.getter_m_iAge());  
  11. }  

 

 

拷贝构造函数声明为(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*

 

 

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

 

[cpp] view plain copy
 
  1. CStudent::CStudent(const CStudent& src) ///< 入参改成const class&  
  2. {  
  3.     copy(&src);  
  4. }  
  5.   
  6. CStudent::CStudent(const CStudent* psrc)  
  7. {  
  8.     copy(psrc);  
  9. }  
  10.   
  11. void CStudent::copy(const CStudent* psrc)  
  12. {  
  13.     setter_m_cName(psrc->getter_m_cName());  
  14.     setter_m_nId(psrc->getter_m_nId());  
  15.     setter_m_iAge(psrc->getter_m_iAge());  
  16. }  



 

 

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成员函数的主要内容,如果未能解决你的问题,请参考以下文章

C++类和对象(构造函数析构函数拷贝构造函数赋值运算符重载Const成员)详细解读

C++类和对象(构造函数析构函数拷贝构造函数赋值运算符重载Const成员)详细解读

const成员-拷贝构造函数(copy constructor)

C++类和对象

C++类和对象—— 类的6个默认成员函数及日期类的实现

C++从青铜到王者第三篇:C++类和对象(中篇)