类中的const后置函数可操作常量对象如何理解?

fnwyq 2008-03-26 05:27:55
大家好!
如下:

class ClassName
{
public:
int Fun() const;
.....
}

请问Fun中可操作常量对象如何理?
...全文
993 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
fnwyq 2008-04-02
  • 打赏
  • 举报
回复
感谢LS,几个地方讲得很经典!
但是对于“③ const 参数修饰 和 参数返回类型的const修饰 ”和总结部分的<2>,我想补充或者说不同见解如下:

限定函数的传递值参数:
void Fun(const int Var);
分析:上述写法限定参数在函数体中不可被改变。由值传递的特点可知,Var在函数体中的改变不会影响到函数外部。所以,此限定与函数的使用者无关,仅与函数的编写者有关。 结论:最好在函数的内部进行限定,对外部调用者屏蔽,以免引起困惑。如可改写如下:
void Fun(int Var)
{
const int & VarAlias = Var;
VarAlias ...
....
}


限定函数的值型返回值:
const int Fun1();
const MyClass Fun2();
分析:上述写法限定函数的返回值不可被更新,当函数返回内部的类型时(如Fun1),已经是一个数值,当然不可被赋值更新,所以,此时const无意 义,最好去掉,以免困惑。当函数返回自定义的类型时(如Fun2),这个类型仍然包含可以被赋值的变量成员,所以,此时有意义。

用于指针的两种情况分析:
int const *A; file://A可变,*A不可变
int *const A; file://A不可变,*A可变
分析:const是一个左结合的类型修饰符,它与其左侧的类型修饰符和为一个类型修饰符,所以,int const 限定 *A,不限定A。int *const 限定A,不限定*A。
kuronca 2008-03-31
  • 打赏
  • 举报
回复
Const 最早想法是用于取代预处理器#define 这个宏,从而形成常量的概念。针对常量const对象,const指针及指向const的指针,函数const类型参数,const 函数返回类型, const类成员,及const成员函数,及对const最后理解的一些总结来描述 const。
① const对象和const类型的对象
对于这两个概念的描述如下
1. int const Object; //Object是一个const量是不可以被修改 Object = 2;Error
2. const int Object; //Object是 const int型他所存放的内容不可以被修改
对于1,2这两种const用于对象,表述虽然不同但是效果是一样的。因为对象本身存放着内容对对象的改变就是对于对象内容的改变,同样改变后者也是在改变前者。所以语义上一样的。
② const指针 和 指向const的指针 及两者结合
对于三个概念描述如下
1. int* const p; //指针p是const不能被修改 例如p++; //修改p本身会Error
//修改p指向内容 *p = 2; //OK
2. const int* p; //p是指向一个整形常量的指针指向的内容不可以改变 p++;//OK
// *p = 2; //Error
3. const int* const p; //指针p本身是不能被修改并且p所有有效的内容也不能被
//修改 *p = 2; Error 和 p++; Error
③ const 参数修饰 和 参数返回类型的const修饰
1.const 参数修饰
此时函数参数修饰 const的具体用法 ① ②中用法是一样的
例如 void Fun( const int I ) { I++;} //Error不能修改常量I
2.const修饰函数返回类型用法也是类似于 ①②中,仅仅修饰的对象变化变成一个返回对象
例如:const int Fun() { static int I; return I;}
int Res = (Fun())++ //Error不能修改常量返回对象
④ const类成员 和 const 成员函数
1. const成员
类const成员在构造期间会允许被初始化并且在以后不能被改变。我们就可以知道类const成员和一般const 变量是有所不同的,类const成员是对应于每个对象而言才有意义。因为他在构造期被初始化,只有当类实例化后才会进行构造。所以类const成员可以这样描述: 在类的每一次实例化时被初始化,在这个对象的生存周期中不可改变。
2. const 成员函数
描述: void Class::MemberFun() const {}; //此时这个const修饰的this所有类成员变量都不允许在这个函数体作用后被修改。这在设计上会带来一些好处,能防止你意外的处理带来的问题。
总结:
<1> const 常量 一般编译器不会分配空间只是维护一张表。而当extern 外部引用这个常量或者“&”对这个常量取地址时,编译器才会为其分配地址。Const本身的机制比较复杂。
<2> const 记忆法则 const修饰后面一个最近的名称。我曾初学的时候被const 修饰搞的糊里糊涂,后来慢慢的总结我觉得这样理解最容易的。
例子: const int I; 此时const仅仅修饰int 表明 I不是一个常量但是I的内容是常量。因为c/c++表达 对I的改变就是对I内容的改变所以 I也类似一个const。大家不妨可以用指针const修饰试试理解会有帮助的我想。
<3> 对于所有非const 类型可以无条件转化为 const类型,但是后者不能自动转化为前者除非显式的强制转化去掉const性。这样做是有意义的,因为const类型是非const的一个子集是一种特殊,由普遍转化为特殊是合理的,就象模板特化,继承的向上映射都是有意义的。
<4> 记住所有const修饰的内容并不是永远不可改变,如果人为的强制转化编译器是不会提醒的。因为它没有义务这么做,所以我们对其转化时要小心。
<5> 在const类成员函数处理时,我们引入了mutable修饰类成员变量,经过其修饰的成员变量可以在const类成员函数中被修改,编译器是允许的。而其他未被mutable修饰的成员还是按照const规则不能在const成员函数中被改变。
--------------------------------------------------------------------------------



函数后面加“const”与不加是两个不同函数,如:

#include

using namespace std;

class A
{
public:
A(int i, int j){a = i; b = j;}
void print();
void print() const;
private:
int a, b;
};

void A::print()
{
cout << "hello!" << a << b << endl;
}
void A::print() const
{
cout << "hello const!" << a << b << endl;
}

int main()
{
A ss(3,6); // 定义A的对象时,没有用“const”
ss.print();
A const dd(20,2); // 定义A的对象时,用了“const”
dd.print();
}
xuewei198198 2008-03-30
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 cad_vc 的回复:]
class ClassName
{
public:
int Fun() const;
.....
}

类的非静态成员函数有个this指针,函数后面的const就是修饰this的;

int Fun() const; == int Fun(const ClassName* const this);
[/Quote]
const 对象、指向const对象的指针或引用只能用于调用其const成员函数,如果尝试用它们来调用非const成员函数,则是错误的。
pzhuyy 2008-03-30
  • 打赏
  • 举报
回复
Int Fun () const; Such definition is the Fun statement for often the
member function, its function is may quote often in the object data
member, but cannot revise wants to revise must state often the object
in data member with mutable

Often the object is cannot transfer its non- const type
regarding the member function, therefore needs to define often the
member function to quote
xrongfu 2008-03-29
  • 打赏
  • 举报
回复
同意6楼的看法
paidfighting 2008-03-29
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 fnwyq 的回复:]
不知道什么情况下才适合这样用?或者说怎样去体会这一用法的精髓呢?..[/Quote]

如果你写一个大的工程,当某个对象的内容出现了意外的变化时,你可能需要去检查所有非const的函数,有了const,检查工作大大减少

而对于const对象(它也只会调用const成员函数),你可以放心使用它,因为使用前和使用后它的状态完全不变
xue100200 2008-03-29
  • 打赏
  • 举报
回复
首先,int Func() const{...}中的const表示的是{...}里引用的外部变量(不管是全局变量的还是成员变量)不会做修改。
然后,关键字mutable相当于告诉编译器“就算是有const的限定,这个变量也要改”,编译器看见这个关键字就明白了“哦,行,你改吧。”
就这样~~
fnwyq 2008-03-29
  • 打赏
  • 举报
回复
不错不错,感谢LS。
fnwyq 2008-03-28
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 steedhorse 的回复:]
“可操作常量对象”应该是翻译过来的说法吧,我猜原文应该类似于:“Can operate on const objects”,说白了,就是可以在常量对象上被调用。而一般的后面不带const的成员函数是不可以在常量对象上被调用的。
[/Quote]
steedhorse正解啊,小试了一下:
class ClassA
{
public:
void Fun1() const;
void Fun2();
...
};

这时如果有const ClassA a;
那么a只能调用Fun1而不能调用Fun2,编译器的错误提示是:
error C2662: “A::fun2”: 不能将“this”指针从“const A”转换为“A &”
其实这也和cad_vc提到的this指针相吻合,但是这种用法几乎没去用到(做得太少...),不知道什么情况下才适合这样用?或者说怎样去体会这一用法的精髓呢?..
zhangwanlong 2008-03-28
  • 打赏
  • 举报
回复
不能修改成员变量……
zhangwanlong 2008-03-28
  • 打赏
  • 举报
回复
不能修改成员变量……
fnwyq 2008-03-27
  • 打赏
  • 举报
回复
多谢大家!虽然还缺少一个“在Fun中是如何操作常量对象的实例”(因为mutable的例子只是说明了如何在Fun中操作非常量对象),显得不够完美,但已经满足。
wonder2007 2008-03-27
  • 打赏
  • 举报
回复
int Fun() const;
这样定义是将Fun声明为常成员函数,其作用是可以引用常对象中的数据成员,但是不能修改
想要修改要将常对象中的数据成员用mutable声明

对于一个常对象是不能调用其非const类型的成员函数的,所以需要定义常成员函数来引用
biosli 2008-03-27
  • 打赏
  • 举报
回复
首先,int Func() const{...}中的const表示的是{...}里引用的外部变量(不管是全局变量的还是成员变量)不会做修改。
然后,关键字mutable相当于告诉编译器“就算是有const的限定,这个变量也要改”,编译器看见这个关键字就明白了“哦,行,你改吧。”
就这样~~
fnwyq 2008-03-27
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 biosli 的回复:]
mutable 你的参数比如:

C/C++ code

class ClassName
{
public:
int Fun(const int data) const
{
m_data = data;
return 1;
}
.....
private:
mutable int m_data;
}
[/Quote]
[Quote=引用 9 楼 ttkk_2007 的回复:]
就是对成员变量,他只能读,不能写(除非成员变量是mutable的)
而且他也只能访问其他的const函数
[/Quote]
两位能不能形象解释一下mutable这个关键字?最好能从C++的实现原理上说明一下和普通未用mutable修饰的变量之间的区别,谢谢!
hxxwcc 2008-03-27
  • 打赏
  • 举报
回复

class Example
{
public:
void Foo1() const
{
Foo2();//correct
Foo3();//not correct..
mem=0;//not correct..
}
void Foo2() const;
void Foo3();
int GetMem() const{return mem;}//correct
private:
int mem;
};
hxxwcc 2008-03-27
  • 打赏
  • 举报
回复

class Example
{
public:
void Foo1() const
{
Foo2();//correct
Foo3();//not correct..
mem=0;//not correct..
}
void Foo2() const;
void Foo3();
int GetMem() const{return mem;}//correct
private:
int mem;
};
Kratos 2008-03-27
  • 打赏
  • 举报
回复
只能操作常量的函数
CrazyAzreal 2008-03-27
  • 打赏
  • 举报
回复
常量对象没看懂
是不是就是指用const修饰的变量啊?
晨星 2008-03-27
  • 打赏
  • 举报
回复
“可操作常量对象”应该是翻译过来的说法吧,我猜原文应该类似于:“Can operate on const objects”,说白了,就是可以在常量对象上被调用。而一般的后面不带const的成员函数是不可以在常量对象上被调用的。
加载更多回复(10)

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧