include <iostream>
2 #include <string>
3 using namespace std;
4
5 class person
6 {
7 private:
8 int id;
9 string name;
10 public:
11 person(int id, string name):id(id), name(name)
12 {
13 cout << “invoke con” << endl;
14 }
15 void show();
16 ~person()
17 {
18 cout << “invoke decon ~” << endl;
19 }
20 string get_name()const
21 {
22 return name;
23 }
24 void set_name(string n)
25 {
26 name = n;
27 }
28
29 };
30
31 void person::show()
32 {
33 cout << “id: ” << id << ” name: ” << name << endl;
34 }
35
36 string format(person *ps)
37 {
38 return “[" + ps->get_name() + "]“;
39 }
40
41 string format(const person &ps)
42 {
43 //成员函数get_name定义时如果没有末尾的const,将不能在此处调用。因为ps是const的引用
44 // ps.set_name(“m”);
45 return “&” + ps.get_name() + “&”;
46 }
47
48 int main(void)
49 {
50 person p(1, “a”);
51 p.show();
52
53 cout << “format: ” << format(&p) << endl;
55 cout << “format&: ” << format(p) << endl;
56
57
58 return 0;
59 }
1. const在函数返回值前:
返回const值,意思指返回的原函数里的变量的初值不能被修改,但是函数
按值返回的这个变量被制成副本,能不能被修改就没有了意义,它可以被赋给任何
的const或非const类型变量,完全不需要加上这个const关键字.但这只对于内部
类型而言(因为内部类型返回的肯定是一个值,而不会返回一个变量,不会作为左
值使用),对于用户自定义类型,返回值是常量是非常重要的,
X Fuction1 () { return X(); }
const X Fuction2 () { return X(); }
如有上面的自定义类X,和函数Fuction1()和Fuction2(),我们进行如下操作时:
Fuction1()=X(1); //没有问题,可以作为左值调用
Fuction2()=X(1); //编译错误,const返回值禁止作为左值调用.因为左值
把返回值作为变量会修改其返回值,const声明禁止这种修改。
返回的类型为const型不能被修改
对于int来说没有什么意义 返回值只能为右值本身就是const
2. const在函数末尾:
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 关键字只能放在函数声明的尾部,大
概是因为其它地方都已经被占用了。
3.const修饰返回值:
当返回值是自定义类型时,函数调用表达式是可以作为左值的:
person buildArlen()
{
person p(1, “arlen”);
return p;
}
buildArlen() = person(11, “ii”);
当然,如果返回值是内建类型如int这些,函数调用表达式是不可以作左值的,你可以试试。所以说,const如果修改返回内建类型是没有意义的。
但修饰返回自定义类型的函数就有意义了,你猜对了,如果是const person buildArlen()这样的声明,在使用时把buildArlen()看作一个自定义类型的变量就可以了,这个变量不但已经有值而且这个变量还是const的。
const person buildArlen()
{
person p(1, “arlen”);
return p;
}
buildArlen() = person(11, “ii”); //报错!buildArlen() 是const的,不能再被赋值。
要注意:以下代码是ok的:
const person buildArlen(){…}
person ps = p.buildArlen();
ps.set_name(“xx”); //这行是没有问题的。
4. const修饰指针类型返回值:
a. 定义:const person * buildArlen(){…}
调用:const person *pt = buildArlen(); //必须在前面有const,无则报错
b. 定义:person const * buildArlen(){…}
调用:const person *pt = buildArlen(); //是的,跟a是一样的。你也可以把const放在紧挨*的左侧:person const *pt = buildArlen();一个意思。
c. 定义:person * const buildArlen(){…}
调用:
person *pt= buildArlen();//前面加不加const都ok。
小结:如果返回值是自定义类型的指针,就可以直接将整个函数调用看作一个变量。为什么上述a,b在接受返回值时要在前面加const?因为普通变量也是如此的:
int i = 8;
const int *pi = &i;
const int *ptest = pi;//如果去掉前面的const则会报错。why?因为pi指向的变量值不能变,而ptest也是指向同一变量i的地址,所以ptest也必须用const修饰,否则i的值就可能会变。
总结:
返回自定义类型的函数调用可以作左值;作右值时类比普通变量。
返回自定义类型的指针的函数调用不可以作左值;作右值时类比普通变量。
返回内建类型或内建类型指针的函数调用不可以作左值;作右值类比普通变量。