#include <iostream>
class abc
{
private:
double x;
public:
abc(double y);
abc();
~abc();
abc& Comp(abc& n);
void show();
};
abc::abc(double y)
{
x=y;
}
abc::abc()
{
x=0.0;
}
abc::~abc()
{
}
abc& abc::Comp(abc& n)
{
if (n.x>x)
return n;
else
return *this;
}
void abc::show()
{
std::cout<<"x="<<x<<std::endl;
}
int main()
{
abc A=abc(55.43);
abc B=abc();
abc *p=&B.Comp(A);
p->show();
return 0;
}
//举个小栗子,代码中有一个类abc,一个私有成员x,一个对比两个对象的函数Comp和一个显式函数show
//上面的程序,不带任何const限定,程序可以通过编译并正常运行
//测试工具:DEV C++
//通过试验来了解何时使用const来限定成员函数,以及哪些限定位置是有联系的!
//我们知道,如果创建一个const类型的对象,那么调用它的成员函数需要进行const限定,因为无法保证该成员函数的代码是否会修改对象的数据,这就是需要使用const的时机!
//第一次实验,我们将Comp()函数的参数,改成const限定的参数,即“保证传递的引用对象不会被无意间修改”
#include <iostream>
class abc
{
private:
double x;
public:
abc(double y);
abc();
~abc();
abc& Comp(const abc& n); //此处参数添加cosnt限定
void show();
};
abc::abc(double y)
{
x=y;
}
abc::abc()
{
x=0.0;
}
abc::~abc()
{
}
abc& abc::Comp(const abc& n)
{
if (n.x>x)
return n;
else
return *this;
}
void abc::show()
{
std::cout<<"x="<<x<<std::endl;
}
int main()
{
abc A=abc(55.43);
abc B=abc();
abc *p=&B.Comp(A);
p->show();
return 0;
}编译错误提示:[Error] invalid initialization of reference of type 'abc&' from expression of type 'const abc'错误原因是,Comp函数传递的是一个const对象引用,而函数把这个const引用作为返回值,但Comp本身的返回值类型,也就是原型中并没有声明返回值是一个const对象。因此,编译器会报错。假如把Comp函数中的返回值n换成*this,也就是说不把传递进来的cosnt对象引用n作为返回值,程序会正常编译,冲突消失;
正确的解决方案是:Comp函数参数带有const限定,并被返回,那么无论是原型还是定义中,参数和返回值都需要const限定;
结论:如果函数参数是const限定的,并被返回,函数的返回值也需要const限定;
第二次实验,按照第一个实验结论修改程序,我们重新运行,但仍然报错,这里报错的是下列两个语句:
abc *p=&B.Comp(A);
p->show();
*/
#include <iostream>
class abc
{
private:
double x;
public:
abc(double y);
abc();
~abc();
const abc& Comp(const abc& n);
void show();
};
abc::abc(double y)
{
x=y;
}
abc::abc()
{
x=0.0;
}
abc::~abc()
{
}
const abc& abc::Comp(const abc& n)
{
if (n.x>x)
return n;
else
return *this;
}
void abc::show()
{
std::cout<<"x="<<x<<std::endl;
}
int main()
{
abc A=abc(55.43);
abc B=abc();
//abc *p=&B.Comp(A);
//p->show();
return 0;
}我们先不管这两条语句为什么出错,先让注释掉,再运行,程序正常编译;编译上述代码无误;
我们先添加一条这样的代码:B.Comp(A);,再次运行,仍然会正确编译;注意Comp函数返回的是一个cosnt限定的对象引用
假设,我们根据额外添加的这条语句,想直接调用show函数来查看x的值,因为函数返回的是对象引用,因此可以直接用上条语句调用show函数,即B.Comp(A).show();不幸的是,编译报错:[Error] passing 'const abc' as 'this' argument of 'void abc::show()' discards qualifiers [-fpermissive];错误原因就是文章开头所说的,B.Comp(A)这个函数返回的是一个const类型的对象,它不同于A和B,而一个独立的abc类的,且被const限定了,这个时候调用show函数,由于show函数没有被const限定,它的代码可能会导致无意间修改了这个const对象的值,这就是错误的根源;所以正确的做法是,在show()的后面添加const限定;
为什么在后面限定?第一,show没有返回值,不能放到前面,因为前面是限定返回值类的;第二,show没有参数,因此没法在括号中去限定参数,因此只能放到后面来限定show函数;因此,show函数成为了“const限定的类成员函数”;
error:B.Comp(A).show();
修改原型:void show() const;
修改定义:void abc::show() const;
修改后,程序可以正常编译和运行
结论:调用成员函数的对象如果是const限定的,这个被调用的函数也需要const限定;
第三次实验,将上述代码中暂时注释的两条语句去掉注释,进行编译报错;
这个错误非常明显,由于定义的abc类指针没有被const限定,而后面的函数返回的是一个const类型的对象,造成冲突(注意,返回对象需要使用取地址运算符将地址赋值给指针)
修改:在类指针前添加const限定,cosnt abc* p = &B.Comp(A);
//下面是正确的代码:#include <iostream>
class abc
{
private:
double x;
public:
abc(double y);
abc();
~abc();
const abc& Comp(const abc& n);
void show() const;
};
abc::abc(double y)
{
x=y;
}
abc::abc()
{
x=0.0;
}
abc::~abc()
{
}
const abc& abc::Comp(const abc& n)
{
if (n.x>x)
return n;
else
return *this;
}
void abc::show() const
{
std::cout<<"x="<<x<<std::endl;
}
int main()
{
abc A=abc(55.43);
abc B=abc();
B.Comp(A).show();
const abc *p=&B.Comp(A);
p->show();
return 0;
}
//第四次实验,我们发现,没有在show函数后面添加const限定的时候,仅使用语句B.Comp(A)时,程序不会报错,仅在用它来调用show函数时出错;通过前面的了解,我们知道Comp函数的返回值是一个const限定的对象引用,而必须这样的原因是,函数代码块中存在一个返回const对象的语句,而这个根源就是参数是const型的,因此,一旦满足参数是const限定的,返回值是const限定的,就必须在该加const的位置上添加const;
那Comp函数需不需要const限定?
/*
const abc C=abc(34.6); //C是一个const对象
C.Comp(B); //ERROR:而Comp不是const限定的,即便Comp函数的代码并没有改变任何对象的值;
*/
正确的做法是,在Comp函数的原型和定义后面添加const限定;
总结:何时使用const?
1.在你不打算修改,并且也为了防止无意间修改变量(引用,指针,对象等)的位置添加const限定;
2.非const允许匹配const以及非const,但const必须匹配const;比如返回值类型中返回值是const,返回值类型必须是const;但返回值是const,将一个非const返回给const没问题;
//最终的代码:
#include <iostream>
class abc
{
private:
double x;
public:
abc(double y);
abc();
~abc();
const abc& Comp(const abc& n) const;
void show() const;
};
abc::abc(double y)
{
x=y;
}
abc::abc()
{
x=0.0;
}
abc::~abc()
{
}
const abc& abc::Comp(const abc& n) const
{
if (n.x>x)
return n;
else
return *this;
}
void abc::show() const
{
std::cout<<"x="<<x<<std::endl;
}
int main()
{
abc A=abc(55.43);
abc B=abc();
B.Comp(A).show();
const abc *p=&B.Comp(A);
p->show();
const abc C=abc(34.6);
C.Comp(B);
return 0;
}//PS:代码仅供参考,试验中的语句为了考察const的限定和用法,可能存在不好的地方!
本文通过实例探讨C++中何时需要在成员函数中使用const关键字。当函数不会修改对象状态,尤其是当函数接收const对象或参数为const时,应使用const限定。实验表明,const限定会影响函数返回值类型以及类指针的使用,确保不违反const语义。

1144

被折叠的 条评论
为什么被折叠?



