C++ Primer 12章 从const成员函数返回*this

时间:2023-02-09 14:01:06
c++
不能从const成员函数返回指向类对象的普通引用。const成员函数只能返回*this作为一个const引用。这句话的主要意思是什么呢?我怎么就不明白呢?

我明白前文说的:在普通的非const成员函数中,this的类型是一个指向类类型的const指针,可以改变this所指向的值,但不能改变this所保存的地址。在const成员函数中,this的类型是一个指向const类类型的const指针,既不能改变this所指向的对象,也不能改变this所保存的地址

但是,不能从const成员函数返回指向类对象的普通引用,什么是“指向类对象的普通引用”?

23 个解决方案

#1


这里类对象的普通引用应该就是指非const对象的引用,this指向const类型对象,返回的*this刚好是const对象

#2


引用 1 楼 dy106 的回复:
这里类对象的普通引用应该就是指非const对象的引用,this指向const类型对象,返回的*this刚好是const对象

那为什么只能返回*this呢?不能返回其他的指针吗?

#3


这句话的意思就是:

class X
{
   X& get() const { return *this; } // 错误!
   const X& get() const { return *this; } // 正确
}

#4


这个const成员函数不就是限定调用该函数的对象的值不能修改吗?和返回值有什么关系?

#5


"const成员函数不就是限定调用该函数的对象的值不能修改" 这只是表面现象, 实际上是:
const 成员函数里的 this 指针是个 const 的指针.
void X::get() const  等价于 void x_get(const X* this)
正是由于 this 是 const 的, 所以才不能修改 this 对象上的值.

而实际上, 你在 const 函数里一样可以修改对象的值:
void X::get() const {
  const_cast<X*>(this)->x = 0; 
}

#6


引用 5 楼 adlay 的回复:
"const成员函数不就是限定调用该函数的对象的值不能修改" 这只是表面现象, 实际上是:
const 成员函数里的 this 指针是个 const 的指针.
void X::get() const  等价于 void x_get(const X* this)
正是由于 this 是 const 的, 所以才不能修改 this 对象上的值.

而实际上, 你在 ……

那我返回一个普通引用有什么关系呢?限定返回引用是否为const的不应该是函数类型吗?我还是不明白为什么“只能返回*this”

#7


楼主你觉得这个样子行吗

const int i=0;
int &j = i;

#8


没有人说只能返回 *this !!
你不能从一句话里面只截取中间一部分来理解...

这不是技术问题, 是一个语文的问题了!
或许翻译得没那么准确, 但是整句话的意思是明确的. 建议重新学下语文课!

#9


引用 7 楼 sccdyy226 的回复:
楼主你觉得这个样子行吗
C/C++ code?12const int i=0;int &amp;j = i;

这个是不可以的吧!! 不是可以通过改变j的值来修改i了!!

#10


const成员函数返回什么由你声明函数时的类型所决定的,没有规定说只能返回*this。
 我对那句话的理解是:如果你const成员函数的返回类型是指向类对象的普通引用,则不能用*this。但如果你在函数中用new生成了一个对象,返回值是可以用这个生成的对象作为引用的。

#11


看了各位的解释,理解了!!!

#12


就是要确保const的语义一致。

#13


普通引用,确切意思是 非常量引用。
不过这么说,也足以表达意思了。

#14


const成员函数的 const 修饰的是隐藏参数 this 指针。
如果,函数没有参数,只能返回常量引用(*this);
不过如果返回传入的参数,应该可以返回任何引用;

例如
ostream & print(ostream& os) const {return os;};

#15


你按照C言的方式理解就明白多了,看代码.

class A
{
 public:
      const A& fun() const {return *this;};
};

这在C语言相当于

const A& fun(const A *this) {return *this;};

如果你想把那个返回值的 const 给去掉,你想想在C语言中就会是下面的样式:

A& fun(const A *this) {return *this};

你觉得这样合适吗?

#16


const 限定成员函数,就表明此函数不能修改任何的成员变量,如果你返回非const的引用,首先表明你已经对当前的返回的成员变量做了类型的转换;
给成员函数添加const限定,属于可读操作,当你返回普通的应用后,就能够对间接的在外部修改成员变量了,那就会变的有冲突了,
对于*this其实也是一样的,

class Base
{
public:
const Base& get() const
{
   return *this;
}
};


#17


 各位解释的很到位

#18


学习一下吧 C++ Primer 12章 从const成员函数返回*this

#19


这什么破书啊, 扔了吧。 还“普通引用”呢, 怎么没有“豪华引用”啊!无论作者心里多么明的,说“const成员函数只能返回*this作为一个const引用”也是完全错误的 -- 且不说其语文措辞如何蛋疼 -- 不就是一个const_cast的事吗? 

另外说一个茴香豆的茴有4样写法的事:说话 const 指针也可以修改指向的对象 -- 有种修辞叫mutable

#20


引用 19 楼 todd_leftcode 的回复:
这什么破书啊, 扔了吧。 还“普通引用”呢, 怎么没有“豪华引用”啊!无论作者心里多么明的,说“const成员函数只能返回*this作为一个const引用”也是完全错误的 -- 且不说其语文措辞如何蛋疼 -- 不就是一个const_cast的事吗? 

另外说一个茴香豆的茴有4样写法的事:说话 const 指针也可以修改指向的对象 -- 有种修辞叫mutable

这本书叫《C++ Primer》
原文是:
We cannot return a plain reference to the class object from a const member function. A const member function  may return *this  only as a const reference.

这里的翻译有些问题,前面说了may,但后面又说only,那为什么不直接说must之类更肯定的语气?
我的理解是,返回一个*this时只能作为const引用。而不是只能返回*this作为const引用。

const_cast的话,可以这样理解。比如有一个const对象myScreen和一个const成员函数display(),那么你认为这样做合理么? 
myScreen.display().set('*');
返回的是const_cast的*this,然后再修改他的值?语法上来说没什么问题吧,但逻辑上说不通吧!

#21


这段是说如果member function为const
你回传的reference也必须为const,不特指*this


class example
{
public:
    int& get_a() { return a; }
    int const& get_a() const { return a; } //#0

    example& do_something(example const &) { return *this; }
    example const& do_something(example const &) const { return *this; } //#1

private:
    int a;
};

试试看把#0和#1的reference拔掉,看看错误讯息

#22


引用 20 楼 Adol1111 的回复:
Quote: 引用 19 楼 todd_leftcode 的回复:

这什么破书啊, 扔了吧。 还“普通引用”呢, 怎么没有“豪华引用”啊!无论作者心里多么明的,说“const成员函数只能返回*this作为一个const引用”也是完全错误的 -- 且不说其语文措辞如何蛋疼 -- 不就是一个const_cast的事吗? 

另外说一个茴香豆的茴有4样写法的事:说话 const 指针也可以修改指向的对象 -- 有种修辞叫mutable

这本书叫《C++ Primer》
原文是:
We cannot return a plain reference to the class object from a const member function. A const member function  may return *this  only as a const reference.

这里的翻译有些问题,前面说了may,但后面又说only,那为什么不直接说must之类更肯定的语气?
我的理解是,返回一个*this时只能作为const引用。而不是只能返回*this作为const引用。

const_cast的话,可以这样理解。比如有一个const对象myScreen和一个const成员函数display(),那么你认为这样做合理么? 
myScreen.display().set('*');
返回的是const_cast的*this,然后再修改他的值?语法上来说没什么问题吧,但逻辑上说不通吧!


好吧见于对该书及其作者的无比崇敬(虽然我尚未拜读),我收回成见。
不合理的是display只有const版本没有non-const版本,而它的返回值却意在chained call;或者myScreen是个const引用却试图对其调用non-const方法set。
const_cast,存在即合理。并不是所有人都能非常谨慎的、逻辑的使用const,当你试图使用一个第三方类库时,使用const_cast的机会或许相当容易碰到, 别犹豫,它就是为此而存在的。
或者哲学一点, const 修饰函数保证的语义安全性有两个,一个是保证该函数不会不小心修改当前对象,也保证该函数不会从一个const对象中返回整个或部分non-const内容。 如果我们只关注后者, 那display会有const和non-const两个版本,但你如何在non-const版本中保证display不会修改当前对象? 而不声明non-const版本却又无法实现chained call。

#23


引用 22 楼 todd_leftcode 的回复:
Quote: 引用 20 楼 Adol1111 的回复:

Quote: 引用 19 楼 todd_leftcode 的回复:

这什么破书啊, 扔了吧。 还“普通引用”呢, 怎么没有“豪华引用”啊!无论作者心里多么明的,说“const成员函数只能返回*this作为一个const引用”也是完全错误的 -- 且不说其语文措辞如何蛋疼 -- 不就是一个const_cast的事吗? 

另外说一个茴香豆的茴有4样写法的事:说话 const 指针也可以修改指向的对象 -- 有种修辞叫mutable

这本书叫《C++ Primer》
原文是:
We cannot return a plain reference to the class object from a const member function. A const member function  may return *this  only as a const reference.

这里的翻译有些问题,前面说了may,但后面又说only,那为什么不直接说must之类更肯定的语气?
我的理解是,返回一个*this时只能作为const引用。而不是只能返回*this作为const引用。

const_cast的话,可以这样理解。比如有一个const对象myScreen和一个const成员函数display(),那么你认为这样做合理么? 
myScreen.display().set('*');
返回的是const_cast的*this,然后再修改他的值?语法上来说没什么问题吧,但逻辑上说不通吧!


好吧见于对该书及其作者的无比崇敬(虽然我尚未拜读),我收回成见。
不合理的是display只有const版本没有non-const版本,而它的返回值却意在chained call;或者myScreen是个const引用却试图对其调用non-const方法set。
const_cast,存在即合理。并不是所有人都能非常谨慎的、逻辑的使用const,当你试图使用一个第三方类库时,使用const_cast的机会或许相当容易碰到, 别犹豫,它就是为此而存在的。
或者哲学一点, const 修饰函数保证的语义安全性有两个,一个是保证该函数不会不小心修改当前对象,也保证该函数不会从一个const对象中返回整个或部分non-const内容。 如果我们只关注后者, 那display会有const和non-const两个版本,但你如何在non-const版本中保证display不会修改当前对象? 而不声明non-const版本却又无法实现chained call。

《Effective C++》条款3中提到了一种解决方法,就是让non-const版本调用const版本,从而避免该问题。
简单来说就是类似这种形式,先添加const属性,然后再去掉const属性:
Screen& display(){
return const_cast<Screen&>(static_cast<const Screen&>(*this).display());
}

#1


这里类对象的普通引用应该就是指非const对象的引用,this指向const类型对象,返回的*this刚好是const对象

#2


引用 1 楼 dy106 的回复:
这里类对象的普通引用应该就是指非const对象的引用,this指向const类型对象,返回的*this刚好是const对象

那为什么只能返回*this呢?不能返回其他的指针吗?

#3


这句话的意思就是:

class X
{
   X& get() const { return *this; } // 错误!
   const X& get() const { return *this; } // 正确
}

#4


这个const成员函数不就是限定调用该函数的对象的值不能修改吗?和返回值有什么关系?

#5


"const成员函数不就是限定调用该函数的对象的值不能修改" 这只是表面现象, 实际上是:
const 成员函数里的 this 指针是个 const 的指针.
void X::get() const  等价于 void x_get(const X* this)
正是由于 this 是 const 的, 所以才不能修改 this 对象上的值.

而实际上, 你在 const 函数里一样可以修改对象的值:
void X::get() const {
  const_cast<X*>(this)->x = 0; 
}

#6


引用 5 楼 adlay 的回复:
"const成员函数不就是限定调用该函数的对象的值不能修改" 这只是表面现象, 实际上是:
const 成员函数里的 this 指针是个 const 的指针.
void X::get() const  等价于 void x_get(const X* this)
正是由于 this 是 const 的, 所以才不能修改 this 对象上的值.

而实际上, 你在 ……

那我返回一个普通引用有什么关系呢?限定返回引用是否为const的不应该是函数类型吗?我还是不明白为什么“只能返回*this”

#7


楼主你觉得这个样子行吗

const int i=0;
int &j = i;

#8


没有人说只能返回 *this !!
你不能从一句话里面只截取中间一部分来理解...

这不是技术问题, 是一个语文的问题了!
或许翻译得没那么准确, 但是整句话的意思是明确的. 建议重新学下语文课!

#9


引用 7 楼 sccdyy226 的回复:
楼主你觉得这个样子行吗
C/C++ code?12const int i=0;int &amp;j = i;

这个是不可以的吧!! 不是可以通过改变j的值来修改i了!!

#10


const成员函数返回什么由你声明函数时的类型所决定的,没有规定说只能返回*this。
 我对那句话的理解是:如果你const成员函数的返回类型是指向类对象的普通引用,则不能用*this。但如果你在函数中用new生成了一个对象,返回值是可以用这个生成的对象作为引用的。

#11


看了各位的解释,理解了!!!

#12


就是要确保const的语义一致。

#13


普通引用,确切意思是 非常量引用。
不过这么说,也足以表达意思了。

#14


const成员函数的 const 修饰的是隐藏参数 this 指针。
如果,函数没有参数,只能返回常量引用(*this);
不过如果返回传入的参数,应该可以返回任何引用;

例如
ostream & print(ostream& os) const {return os;};

#15


你按照C言的方式理解就明白多了,看代码.

class A
{
 public:
      const A& fun() const {return *this;};
};

这在C语言相当于

const A& fun(const A *this) {return *this;};

如果你想把那个返回值的 const 给去掉,你想想在C语言中就会是下面的样式:

A& fun(const A *this) {return *this};

你觉得这样合适吗?

#16


const 限定成员函数,就表明此函数不能修改任何的成员变量,如果你返回非const的引用,首先表明你已经对当前的返回的成员变量做了类型的转换;
给成员函数添加const限定,属于可读操作,当你返回普通的应用后,就能够对间接的在外部修改成员变量了,那就会变的有冲突了,
对于*this其实也是一样的,

class Base
{
public:
const Base& get() const
{
   return *this;
}
};


#17


 各位解释的很到位

#18


学习一下吧 C++ Primer 12章 从const成员函数返回*this

#19


这什么破书啊, 扔了吧。 还“普通引用”呢, 怎么没有“豪华引用”啊!无论作者心里多么明的,说“const成员函数只能返回*this作为一个const引用”也是完全错误的 -- 且不说其语文措辞如何蛋疼 -- 不就是一个const_cast的事吗? 

另外说一个茴香豆的茴有4样写法的事:说话 const 指针也可以修改指向的对象 -- 有种修辞叫mutable

#20


引用 19 楼 todd_leftcode 的回复:
这什么破书啊, 扔了吧。 还“普通引用”呢, 怎么没有“豪华引用”啊!无论作者心里多么明的,说“const成员函数只能返回*this作为一个const引用”也是完全错误的 -- 且不说其语文措辞如何蛋疼 -- 不就是一个const_cast的事吗? 

另外说一个茴香豆的茴有4样写法的事:说话 const 指针也可以修改指向的对象 -- 有种修辞叫mutable

这本书叫《C++ Primer》
原文是:
We cannot return a plain reference to the class object from a const member function. A const member function  may return *this  only as a const reference.

这里的翻译有些问题,前面说了may,但后面又说only,那为什么不直接说must之类更肯定的语气?
我的理解是,返回一个*this时只能作为const引用。而不是只能返回*this作为const引用。

const_cast的话,可以这样理解。比如有一个const对象myScreen和一个const成员函数display(),那么你认为这样做合理么? 
myScreen.display().set('*');
返回的是const_cast的*this,然后再修改他的值?语法上来说没什么问题吧,但逻辑上说不通吧!

#21


这段是说如果member function为const
你回传的reference也必须为const,不特指*this


class example
{
public:
    int& get_a() { return a; }
    int const& get_a() const { return a; } //#0

    example& do_something(example const &) { return *this; }
    example const& do_something(example const &) const { return *this; } //#1

private:
    int a;
};

试试看把#0和#1的reference拔掉,看看错误讯息

#22


引用 20 楼 Adol1111 的回复:
Quote: 引用 19 楼 todd_leftcode 的回复:

这什么破书啊, 扔了吧。 还“普通引用”呢, 怎么没有“豪华引用”啊!无论作者心里多么明的,说“const成员函数只能返回*this作为一个const引用”也是完全错误的 -- 且不说其语文措辞如何蛋疼 -- 不就是一个const_cast的事吗? 

另外说一个茴香豆的茴有4样写法的事:说话 const 指针也可以修改指向的对象 -- 有种修辞叫mutable

这本书叫《C++ Primer》
原文是:
We cannot return a plain reference to the class object from a const member function. A const member function  may return *this  only as a const reference.

这里的翻译有些问题,前面说了may,但后面又说only,那为什么不直接说must之类更肯定的语气?
我的理解是,返回一个*this时只能作为const引用。而不是只能返回*this作为const引用。

const_cast的话,可以这样理解。比如有一个const对象myScreen和一个const成员函数display(),那么你认为这样做合理么? 
myScreen.display().set('*');
返回的是const_cast的*this,然后再修改他的值?语法上来说没什么问题吧,但逻辑上说不通吧!


好吧见于对该书及其作者的无比崇敬(虽然我尚未拜读),我收回成见。
不合理的是display只有const版本没有non-const版本,而它的返回值却意在chained call;或者myScreen是个const引用却试图对其调用non-const方法set。
const_cast,存在即合理。并不是所有人都能非常谨慎的、逻辑的使用const,当你试图使用一个第三方类库时,使用const_cast的机会或许相当容易碰到, 别犹豫,它就是为此而存在的。
或者哲学一点, const 修饰函数保证的语义安全性有两个,一个是保证该函数不会不小心修改当前对象,也保证该函数不会从一个const对象中返回整个或部分non-const内容。 如果我们只关注后者, 那display会有const和non-const两个版本,但你如何在non-const版本中保证display不会修改当前对象? 而不声明non-const版本却又无法实现chained call。

#23


引用 22 楼 todd_leftcode 的回复:
Quote: 引用 20 楼 Adol1111 的回复:

Quote: 引用 19 楼 todd_leftcode 的回复:

这什么破书啊, 扔了吧。 还“普通引用”呢, 怎么没有“豪华引用”啊!无论作者心里多么明的,说“const成员函数只能返回*this作为一个const引用”也是完全错误的 -- 且不说其语文措辞如何蛋疼 -- 不就是一个const_cast的事吗? 

另外说一个茴香豆的茴有4样写法的事:说话 const 指针也可以修改指向的对象 -- 有种修辞叫mutable

这本书叫《C++ Primer》
原文是:
We cannot return a plain reference to the class object from a const member function. A const member function  may return *this  only as a const reference.

这里的翻译有些问题,前面说了may,但后面又说only,那为什么不直接说must之类更肯定的语气?
我的理解是,返回一个*this时只能作为const引用。而不是只能返回*this作为const引用。

const_cast的话,可以这样理解。比如有一个const对象myScreen和一个const成员函数display(),那么你认为这样做合理么? 
myScreen.display().set('*');
返回的是const_cast的*this,然后再修改他的值?语法上来说没什么问题吧,但逻辑上说不通吧!


好吧见于对该书及其作者的无比崇敬(虽然我尚未拜读),我收回成见。
不合理的是display只有const版本没有non-const版本,而它的返回值却意在chained call;或者myScreen是个const引用却试图对其调用non-const方法set。
const_cast,存在即合理。并不是所有人都能非常谨慎的、逻辑的使用const,当你试图使用一个第三方类库时,使用const_cast的机会或许相当容易碰到, 别犹豫,它就是为此而存在的。
或者哲学一点, const 修饰函数保证的语义安全性有两个,一个是保证该函数不会不小心修改当前对象,也保证该函数不会从一个const对象中返回整个或部分non-const内容。 如果我们只关注后者, 那display会有const和non-const两个版本,但你如何在non-const版本中保证display不会修改当前对象? 而不声明non-const版本却又无法实现chained call。

《Effective C++》条款3中提到了一种解决方法,就是让non-const版本调用const版本,从而避免该问题。
简单来说就是类似这种形式,先添加const属性,然后再去掉const属性:
Screen& display(){
return const_cast<Screen&>(static_cast<const Screen&>(*this).display());
}