C++总的const使用说明
C++总的const使用说明
1. const修饰类成员变量
程序:
#include <iostream>
using namespace std; class A
{
public:
A(int size) : SIZE(size) {};
private:
const int SIZE;
}; int main()
{
A a();
}
说明:
(1) 在类中声明变量为const类型,但是不可以初始化;
(2) const常量类的成员变量的初始化必须在构造函数初始化列表中初始化,而不可以在构造函数函数体内初始化。
(3) 如果其作为C类的成员定义,因为不可以在C类定义创建对象,则可以采用如下措施:
使用指针,然后在C类的构造函数中,用new 在堆空间创建对象,然后天数const的成员初始化。
此时的const变量属于具体的一个对象,如何在整个类中都恒定不变呢?
答案是利用枚举
#include <iostream>
using namespace std; class A
{
private:
enum {SIZE = };
public:
int array[SIZE];
}; int main()
{
A a;
}
问题说明:
(1)枚举常量不会占据对象的存储空间,在编译时被全部求值
(2)但是,它隐含的数据对象类型为整形,不能表示其他类型。
2. 必须在构造函数的初始化列表中初始化的情况
(1)类的const常量;
(2)类的引用类型成员;
#include <iostream>
using namespace std; class A
{
public:
A(int &v) : i(v), p(v), j(v) {}
void print_val() { cout << "hello:" << i << " " << j << endl;}
private:
const int i;
int p;
int &j;
}; int main(int argc ,char **argv)
{
int pp = ;
A b(pp);
b.print_val();
}
究其因
① const对象或引用只能列表初始化但是不能赋值。
② 构造函数的函数体内只能做赋值而不是初始化,因此初始化const对象或引用的唯一机会是构造函数函数体之前的初始化列表中。
③ 明白两个概念:
从无到有叫初始化,初始化(调用拷贝构造函数)创建了新对象;
赋值(调用赋值操作符)没有创建新对象,而是对已有的对象赋值。
(3)没有默认构造函数的类类型成员
#include <iostream>
using namespace std; class Base
{
public:
Base(int a) : val(a) {}
private:
int val;
}; class A
{
public:
A(int v) : p(v), b(v) {}
void print_val() { cout << "hello:" << p << endl;}
private:
int p;
Base b;
}; int main(int argc ,char **argv)
{
int pp = ;
A b(pp);
b.print_val();
}
原因同样是创建对象时,要初始类成员的每一个成员。
(4)如果类存在继承关系,派生类必须在其初始化列表中调用基类的构造函数;
#include <iostream>
using namespace std; class Base
{
public:
Base(int a) : val(a) {}
private:
int val;
}; class A : public Base
{
public:
A(int v) : p(v), Base(v) {}
void print_val() { cout << "hello:" << p << endl;}
private:
int p;
}; int main(int argc ,char **argv)
{
int pp = ;
A b(pp);
b.print_val();
}
3. const成员函数与非const 成员 函数问题
(1) 任何不修改数据成员的函数都应该声明为const类型。
如果在编写const成员函数时,①不慎修改了数据成员,②或调用了其他非const成员函数,编译器就会指出错误。应该养成一个好的习惯。
注意:在const修饰类的成员数据时,一般在const声明在函数声明的后边;
#include <iostream>
using namespace std;
class Stack
{
public:
void Push(int item);
int Pop(void);
int GetCount(void) const;//const 后置
private:
int m_num;
int m_data[];
}; int Stack::GetCount(void) const
{
++m_num; //编译错误,企图修改数据成员
Pop(); //编译错误,企图调用非const函数
return m_num;
}
(2)同一个类中,可以仅通过是否是const定义两个函数名字、参数、返回值完全相同的两个成员函数,依据类对象是否为const对象分别调用。
程序:
#include <iostream>
using namespace std; class A
{
public:
A(int v): val(v) {}
void print_val() { cout << "not const:" << val << endl;}
void print_val() const { cout << "const print_val:" << val << endl;}
private:
int val;
};
int main(int argc ,char **argv)
{
A b();
b.print_val(); const A a(12);
a.print_val();
}
输出:
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAASYAAAAtCAIAAACMFlH6AAADxElEQVR4nO2c26GsIAxFqYuCqMdqbMZivB/Hi4QkEIXB116fjobEYQtGiFsBAANxVzsAwLeA5AAYCiQHwFD6Sm4Ozk9LV5MX0C+KZfLOOT+Jhwlh7tEeeACQHKdbFJN33ntZctDYV4HkOJ2imINzYZ4DJAdS3LruE50wJ3Me1lHWv14kz4XIL00TJtrGxHqn6oM5inRaF+Y57FYORLEZkezHE/y0rJAcoOyj3ORdCHv/mHze07Ijc+AdrnV8mINjbZADVR8ORsEasEYRxamcGZWmSi7s8tZ1C94HkRzpfPRRLD6YWd9sk5zURnrM4kM5ijUOPiVMUWyaU9Syt6pJLvESg96noKNc+r/TjiD3irw/NUmu2vMsPpSjiOcU54ytY/UyJSkTSXLdWwQPwig5pU90lVztYpMPFsllV7PfGwVATZokpzxNwBv54ihXM9s+PT6cRoLkvoNVciPe5aQRJ8X4LleSnDTmnJNcNWNZaDEHL3Nfwiq5lSUeyBtLck6eDzySjsszluxI1Ye65KhLZ6OoZSzTE7Nrs5CWydetgPdAvsvFGRA7sEHmTLKWyKetEz0pn5exp7/qgyWKvwEsNXE2inLGMrehKvbkXQLPBcuaARgKJAfAUCA5AIYCyQEwFEgOgKFAcgAMBZIDYCiQHABDgeRksCYE/Ii7Se4u21jaJHd9FMkCm/ZNw+oC0KVXM18CkvsF94nirCdRTCFoi83pWlG+PBbIQHK/4D5RtHuiWFj49vr7RH1rqOQeUupHJFlnnJqil0fnYmESdlJprlQPs1MU6UXSTafNFDp6RQaGLUgHhIQ9SBZ2yT2n1I/OHJz3+aZsbnDfTxB3HPCuonpSDfMXNWBKJVsWyQWTJ5YtSOZYsOvPxn/JParUT+lqsf9zXVce7SVPqmG2T7HyG1XrzfrvFU/qW5CssWBWaWWT3EtK/Yj7yrkbte3nZU8MYXYtWGTw97TkDFhLDGKAM7JJ7iWlfuSqB3K9CJOtiyRH741kjb8zXiY56O0Yo0e5mtlRo9zdJbeHwktF8G+Gl41ypddIIPP/Xe5RpX5U7O9yt5dcNMtfgHl7pyXXlLEUU1Oghp6xvG+pHx2esRQ+Hw2QXGvZpWjEh8CNZ4/H/cPFkSh2x85lLKVnNFKWFsh3uaeU+lHZtEQL/Szkd4Es+yixWTHXZepTUEhfbUXv4rJQ2VWi4F7KL8ClW6U1AclVudvqkzZMwxcAVwLJATAUSA6AobxHcuZlhwBcyXsk9wC0nAPyD18CkgNgKJAcAEOB5AAYyj86qS44Lae6oAAAAABJRU5ErkJggg==" alt="" />
总结:
同函数名、参数、返回值可以仅通过是否为const来定义为类的两个成员函数。
在调用时,const对象调用const成员函数,非const对象调用非const成员函数。
(3)非const的成员函数,可以调用const的成员函数,
当一个类只有const成员函数的时候,非const对象也可以调用const成员函数:
class A
{
public:
A( void )
{
} void func( void ) const
{
cout << "const version" << endl;
}
}; int _tmain(int argc, _TCHAR* argv[])
{
//非const对象调用const成员函数 A obj;
obj.func( ); //const对象调用const成员函数
const A obj_const;
obj_const.func( ); system( "PAUSE" );
return EXIT_SUCCESS;
return ;
}
(4)const对象是不可以调用类中的非const成员函数
我们知道c++在类的成员函数中还会隐式传入一个指向当前对象的this指针,所以在test类中,实际的print函数应该是这样的void print(test * this);,这代表一个指向test对象的指针this被传入到了print函数中
假如现在我们用test类创建一个对象,
test obj1(12);
obj1.print();
第二句,obj1.print();其实相当于print(&obj1);,即把当前的对象obj1的指针传递到print()函数,这是没问题的
如果用test类创建一个const对象,然后去调用print()函数呢?这就会出现问题
const test obj2(122);
obj2.print();
这时obj2对象的指针就会传递给test *this 指针,而obj2的地址翻译成指针类型应该是这样的,const test* this,即这时会出现类型不匹配的错误,在visual studio 中会出现类似于下面的错误:
所以通过上面的说明,我们知道了为什么const 对象不能调用非const成员函数。
4. const的一些问题
(1)不可以在const函数中改变成员变量的值,那么有没有办法改变?
答案是可以的,把成员变量声明为mutable类型。看程序
#include <iostream>
using namespace std; class A
{
public:
A(int v): val(v) {}
void print_val() { cout << "not const:" << val << endl;}
void print_val() const { val++; cout << "const print_val:" << val << endl;}
private:
mutable int val;
};
int main(int argc ,char **argv)
{
A b();
b.print_val(); const A a();
a.print_val();
}
输出:
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAM0AAAAvCAIAAADPUtm3AAADpklEQVR4nO2dS5qlIAyFWRd76SmjXkGvwtW4GRdjD8rilQSicBG955+VV0MSjxEEvjI7AJ/H3O0A+AqgMzAC8+fvv7t9AO8HOgMj6K6z1Rm7bF1N3kC/KLbFGmPswh5OcGuP9iYFOmPpFsVijbWW19mrhZUBnbF0imJ1xrh1ddDZr85+67hbo5JOsrP/pI4v9ckvTe+DtI2F3BLRB3UU8VvLrasLVk5EcRjh7PsT7LLt0FlWzxZrnAtJWWye3uzI6miWWyvB6gxpIzlQ9eFkFKQBbRRekcKZXl6izlzQtCzWd5DrLMl4+tCxjyC5IW0649qIj2l8KEex+zJTQhXFITRBIqFVSWeRl68vb6SexcGm0fOpyJPYpLNqujU+lKPw5xRfia1VeVuivj+ns+4tTo5eZ0IiuuqsdrHKB43OsqvJ7413PTWp0pnwCL2FL61nNbPtb//T4yHojP3roHP/jKstMcr+WUlnXHW5prPqeLPQYs7bO2gndLaTHnTSC4nOyUdzZwZT+XiTHKn6UNdZ6tLVKGrjzfjE7NospG2xdSvPJv9+5gs8OXCQvBJ4ASWfoC6kL3/tkOdc9EETxU+pik1cjaI83sxtiDK9mKVngXl0MALoDIwAOgMjgM7ACKAzMALoDIwAOgMjgM7ACKAzkS/4Sj+OCXU2ywqZNp3dH0U05dG+8lScfE1mVuQZWujsQ8wTxVVPvIKcE1Y3ZNO+dGo6AJ19iHmiaPdEbUFedUJ09pA9ICzRxHZsKr3cO+cX75OTSm+cepidoogv4pKeNlPQQUUlitVNvXX2nD0gMqsz1ubLWanBsGrDr+ugCRI9qYb5iX0SpW0NG+eCyhPN6iZtLAUnIp09ag9I6Wr2plMxVx7ikifVMNvfVnmiagsh5d8rntRXN2mW09dKdtDZS/aAsCtyqRu1hbtlTxRhdt3JovD3ss4UKC2wL46DoLOX7AHhF0nzy8tVtm7SWZobzhrtB96ss9KZN9SzmtlR9Wx2nYVQ6Mpy+m1vgnp2nMp6EfXPHrUHRETfP5teZ94s7dTS9i7rrOd4U9ZQcbw57x4QGTre3Lixx8d11rofxxuxzlHj2f0M31rORBEcuzbeZD9PKL/TPmUPiMghoHQHyJb8zpCNHTkOK+oNO312msiTPmkWty3VWiUK6iXfqS2n6kSME84HtKEqVGA00BkYAXQGRvAqnamn/MBoXqWzByD1z+We9juAzsAIoDMwAvzfHTAC6AyM4D/5VfHqxqoEAQAAAABJRU5ErkJggg==" alt="" />
说明:
mutalbe的中文意思是“可变的,易变的”,跟constant(既C++中的const)是反义词。
在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。
我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的。但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰
(2)当类中只有const函数,非const对象是否可以调用const函数?
答案是可以的,范围并没有被扩大。
但是:只有const函数时,非const对象不可以调研那个const函数(否则,类的数据变量就会发生变化)。
(3)当类中存在只有 是否为const 不同的两个函数时,const函数是否可以暂时调用那个非const函数?
答案是可以的。用const_cast将转化掉表达式的const性质
#include <iostream>
using namespace std; class A
{
public:
A(int v): val(v) {}
void print_val() { cout << "not const:" << val << endl;}
void const print_val() const { cout << "const print_val:" << val << endl;}
private:
int val;
};
int main(int argc ,char **argv)
{
A b();
b.print_val(); //非const const A *a = new A();
const_cast<A*>(a)->print_val(); //()调用非const的重载函数
a->print_val(); //调用const的从在函数
}
输出:
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAANMAAABGCAIAAADZzjZ+AAAD8klEQVR4nO2b27mEIAyEqYuCqIdqaMZiPA/HD4EEiIJG1/kfXQ0JO8vFZcwKgAZGOwHwUaA8oAOUB3SA8oAOUB7QYaLygjPWL/Pi6TCvisVbY4z17OUMF2a09zKgvIJpVXhrrLW88j4ptQIor2BSFcEZ40JwUF4NE0d/F5KJgPTX+t+Z/ASRfTI0i+RtePIlVXMQV5HOdS4Et0c5UMUWhIsfb7B+WaG8OtuY561xbu8mb8sOL64ER/t9dLQIzpA2sgvdHA5WQRqQVhE1WrkzCq6qPLervC7f32ZXXvYd5D9M9mdKvqIx5XFtpNckObSrWONQ1EJUxSa9imj2VmvKS7L87BCYjHlp+Xl/8J1TduuQ8rpfgCSHdhXxnuZEOjpyLz7ZVXDKm97iS5Eor9I1U5XXe1iUg0R5xdPk80Ed5CFFyqv8qH6dz415vbDja4bDOy0oL7l8/zqPG39ShOu8lvK4Eeic8rp720aLJV9d6ImUt5K1ebaaSe4pd45HNm7l3pZc6ebQV16e0tkqenvb9Mbi2aKkxdt+lN/EZBOEC+tKL2xkEwkvqeyV2IkOLScrMhZUc5BU8T+cpSHOVtHe25YxqsI92Uu/AU4MAB2gPKADlAd0gPKADlAe0AHKAzpAeUAHKA/oAOUBHXAavgAOoJuA8grgALoJKK8ADqCbgAMIDiAd4ACCA0gHOIDaIas3NUQDB5CEz52GhwPoIcABBAeQDp8b83ph4QC6CTiA4ADSAQ4gOIB0gAPoTBVwAI2DEwNABygP6ADlAR2gPKADlAd0gPKADlAe0AHKAzpAeQwf/mfhPh6lvKecFxpTnn4Vyd80w5lc5mOC8qbznComZHKdjwnKm85zqhjO5EofU6K8l7hvWJK/8NNQ+eMxuWiSIDe15ql+mZOqSB/iOj1vpqGtjvJ0fUwm5vgS902d4Iy15ZFgGnA/sRLPtNAurGbSLfMKP0rLPrJwKYgyUfYxmRjmLe6b1tOsDKi8+z3VUl67zPE5ruyo3vBS/7yTia6PyUgee4f7hj3VTNPoHX5uZyIoc6qHSJDvaeVJc7jGx2QED73EfcN3EH9oXxRLSXl533DR6HpysvLu8DHdOub1wt415j1deXsp9Lw+fdc4f8y7xcdktgzf476pIl/nPV55MSxdHNP2TitP18dU2ds+131Th+5tF25Xc7nyRp1QMYh1jgYvRon9Tc+RKvbEOu9l9jD00UEf0/4+7y3umypbB+XemyX7vD2H8JNMjCK2Ss3x+LDvndZ1zb8I65clV1+nCpqlko/pUf9hjCFbCIOHAOUBHaA8oMMPKQ+8CigP6ADlAR2gPKADlAd0gPKADlAe0OEPdUnxBhhoZboAAAAASUVORK5CYII=" alt="" />
注意;const_cast<A*> (a)只对本地转化有效,且必须使用类的指针进行处理。
单纯用类转化不行,直接用类的对象不行。
const A a();
const_cast<A> a.print_val();
编译不通过,错误
(4)返回类型是const是怎么回事?
const返回类型只有在修饰指针或引用是才有用。单凭const返回类型不可以重载。
参考网址:
http://www.cnblogs.com/kaituorensheng/p/3244910.html
C++总的const使用说明的更多相关文章
- openssl 1.1.1 reference
openssl 1.1.1 include/openssl aes.h: # define HEADER_AES_H aes.h: # define AES_ENCRYPT 1 aes.h: # de ...
- const extern static 终极指南
const extern static 终极指南 不管是从事哪种语言的开发工作,const extern static 这三个关键字的用法和原理都是我们必须明白的.本文将对此做出非常详细的讲解. co ...
- const in C++
const关键字是C++中常用的类型修饰符,用法非常灵活,使用const将大大改善程序的健壮性. const的作用 1. 定义const常量: 比如: const int Max = 100; 2. ...
- LibLinear(SVM包)使用说明之(一)README
转自:http://blog.csdn.net/zouxy09/article/details/10947323/ LibLinear(SVM包)使用说明之(一)README zouxy09@qq.c ...
- Elasticsearch .Net Client NEST使用说明 2.x
Elasticsearch .net client NEST使用说明 2.x Elasticsearch.Net与NEST是Elasticsearch为C#提供的一套客户端驱动,方便C#调用Elast ...
- Delphi 中Format的字符串格式化使用说明(转)
源:Delphi 中Format的字符串格式化使用说明(转) 一.Format函数的用法 Format是一个很常用,却又似乎很烦的方法,本人试图对这个方法的帮助进行一些翻译,让它有一个完整的概貌,以供 ...
- CREELINKS平台_处理器CeCcp资源使用说明(CeCcp的配置与使用)
0x00 CREELINKS平台简介 CREELINKS(创e联)是由大信科技有限公司研发,集合软硬件.操作系统.数据云储存.开发工具于一体,用于物联网产品的设计.研发与生产的平台. 平 ...
- Elasticsearch .net client NEST使用说明 2.x -更新版
Elasticsearch .net client NEST使用说明 目录: Elasticsearch .net client NEST 5.x 使用总结 elasticsearch_.net_cl ...
- c++ 指针与const的三种组合
三种形式 const int a=1; int b=2: 1 const int * ptr1=&a; 2 int * const ptr2 = b; 3 const int * const ...
随机推荐
- 2017.1.9版给信息源新增:max_len、max_db字段
2017.1.8a版程序给信息源增加max_len.max_db字段,分别用于控制:获取条数.数据库保留条数. max_len的说明见此图: max_db的说明见此图: 当max_len和max_db ...
- fiddler 发送get请求
点击Composer 点击执行(Execute) \ 这里演示的是带cookie
- mybatis动态sql trim
trim标记是一个格式化的标记,可以完成set或者是where标记的功能,如下代码: 1. select * from user <trim prefix="WHERE" p ...
- HTML的实际演练1
1.HTML介绍 一个网站的建立都是HTML的,例如大家可以打开F12就可以看到浏览器的一个开发者模式,就可以看到网页的源代码了: 当然这网页他有很多的标签编写组成的,有的显示文字,段落,有的是个超链 ...
- TZOJ 2755 国际象棋(广搜+哈希)
描述 在n*n的国际象棋棋盘中,给定一“马(Knight)”和一“后(Queen)”的位置,问“马”能否在m步之内(包括m步)到达“后”的位置?马的走法是:每步棋先横走或直走一格,然后再斜走一格,即走 ...
- cookie的基本用法
1.创建cookie对象 Cookie newCookie=new Cookie(String ky,String value); 2.写入cookie response.addCookie(newC ...
- Redis的复制特性
对于有扩展平台以适应更高负载经验的工程师和管理员来说,复制(replication)是不可或缺的.复制可以让其他服务器拥有一个不断更新的数据副本,从而使得拥有数据副本的服务器可以用于处理客户端发送的读 ...
- loadrunner11--集合点(Rendezvous )菜单是灰色不能点击
新建场景的时候“Manual Scenario”下的check box不能选中,取消选中就好了.即Vuser不能以百分比的形式. 所以:集合点灰化有两种情况: 脚本没有添加集合点函数 场景中设置以Vu ...
- Bioconductor简介
Bioconductor简介 2012-10-09 ~ ADMIN 源:Bioconductor: open software development for computational biolog ...
- mupdf编译snprintf冲突问题
mupdf-1.6-source\thirdparty\jbig2dec\config_win32.h //# define snprintf _snprintf