const关键字的使用

用法

常变量: const 类型说明符 变量名

常引用: const 类型说明符 &引用名

常对象: 类名 const 对象名

常成员函数: 类名::fun(形参) const

常数组: 类型说明符 const 数组名[大小]

常指针: const 类型说明符* 指针名 ,类型说明符* const 指针名

 

代码中碰到的问题

曾经傻傻地写了如下代码
//update list_relaypoint

fatherWire->list_relaypoint.at(wireIndex).setX(fatherWire->vectorLines[wireIndex]->startPoint.x());

 

编译报错:
/home/kamala/main2/capu/kamala/UI/kamala_Panel/graphics/graphics_wirechild.cpp:158: error: passing ‘const QPointF’ as ‘this’ argument discards qualifiers [-fpermissive]

fatherWire->list_relaypoint.at(wireIndex).setX(fatherWire->vectorLines[wireIndex]->startPoint.x());
^

原因:
at()函数原型为:

const T &at(int i) const;

setX()函数定义为:
Q_DECL_RELAXED_CONSTEXPR inline void QPointF::setX(qreal xpos)
{

xp = xpos;

}
at()中,const修饰成员函数和返回值,const修饰的返回值不能被修改(不能作为左值来使用),
而setX()又是非const修饰的成员函数(即通过该函数可以修改对象),所以at()的const返回值试图去调用非const的setX()会报错。

 

修改为如下写法则不报错:
fatherWire->list_relaypoint[wireIndex].setX(fatherWire->vectorLines[wireIndex]->startPoint.x());

不禁会想,难道这重载的operator[]返回的不是const吗?我们来看一下operator[]的函数原型:

const T &operator[](int i) const; //(1)
T &operator[](int i); //(2)

有两个[]的重载函数,调用哪个呢?

 

由于:
1、const对象只能(注意是“只能”!一开始摘抄的网上的,写的“才能”)调用const版本的function函数,而非const对象可以调用任意一种,通常非const对象调用不是const版本的function函数。
2、按照函数重载的定义,函数名相同而形参表有本质不同的函数称为重载。在类中,由于隐含的this形参的存在,const版本的 function函数使得作为形参的this指针的类型变为指向const对象的指针,而非const版本的使得作为形参的this指针就是正常版本的指针。此处是发生重载的本质。重载函数在最佳匹配过程中,对于const对象调用的就选取const版本的成员函数,而普通的对象调用就选取非const版本的成员函数。

我们这里是非const对象调用[],this形参是正常版本的,所以调用的是第(2)个成员函数,其返回值也不是const类型,因此可以做左值。

 

奇怪的状况:

以下两个例子:
例1:
my_model_chip.ModifyChipByUI(*unitData,pBoard,g_proj.projectList.at(index.i1));
其中,
ModifyChipByUI()函数声明为:

void ModifyChipByUI(conmunication_item_fromProto uiData_rev,Board_Data_t* pBoard,Project_Data_t* pProj);

projectList类型为:

QList<Project_Data_t*> projectList;

at()原型为:

const T &at(int i) const;

故此处at()返回值类型是 const Project_Data_t* &
疑问:为什么此处仍然可以正常调用?

 

例2:
Board_Data_t* pBoard = g_proj.projectList.at(index.i1)->listBoardProp.at(index.i2); //为什么可以这么赋值?

以上两个例子应该是相同的情况,暂时没找到合理的解释,希指教。
:以上2例在Qt开发环境中可以编译通过,而相似的写法(写个小程序myconst.cpp)在终端中用g++则编译报错:
myconst.cpp:63:25: error: invalid conversion from ‘const Hello*’ to ‘Hello*’ [-fpermissive]

struct Hello* ph3 = ph;
^

myconst.cpp:64:13: error: invalid conversion from ‘const Hello*’ to ‘Hello*’ [-fpermissive]

funs(ph2);

 


补充:

下面的两个函数构成重载吗?

void M(int a){} //(1)
void M(const int a){} //(2)

下面的呢?

void M(int& a){} //(3)
void M(const int& a){} //(4)

const在函数中的含义是该值在此函数范围内“无法修改”。站在调用者的角度,所有的值传递都是无法修改实参的。所以,(1)/(2)两个函数在调用者看来,是语义相同的,不能构成重载。
(4)与(3)的区别是,(4)无法修改引用指向的对象,而(3)可以。从调用者的角度,两个函数有不同的语义,构成重载。

int sum (int* a) 和 int sum (const int* a);//也是重载


网上看到的使用const的一些建议:

· 要大胆的使用const,这将给你带来无尽的益处,但前提是你必须搞清楚原委;

· 要避免最一般的赋值操作错误,如将const变量赋值,具体可见思考题;

· 在参数中使用const应该使用引用或指针,而不是一般的对象实例,原因同上;

· const在成员函数中的三种用法(参数、返回值、函数)要很好的使用;

· 不要轻易的将函数的返回值类型定为const;

· 除了重载操作符外一般不要将返回值类型定为对某个对象的const引用;

· 任何不会修改数据成员的函数都应该声明为const 类型。


理解不够透彻,不当之处也请指出。









转载于:https://www.cnblogs.com/duduniya/p/10689670.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值