【问题标题】:How do member functions pass the "this" pointer成员函数如何传递“this”指针
【发布时间】:2014-02-21 15:23:12
【问题描述】:

假设我有一个类 Foo,它有一个返回非常量引用的成员函数,它本身运行一个使用 const this 指针的成员函数:

class Foo{
public:
    Foo& display(std::ostream& os) { do_display(os); return *this; }
private:
    void do_display(std::ostream& os) const { os << contents; }
    std::string contents;
}

display 运行do_display 时,this 指针被隐式转换为指向 const 的指针。那么,为什么当do_display 终止时,display 仍然能够更改它被调用的对象?据我所知,通常不可能将指向 const 的指针分配给指向非 const 的指针。任何见解都值得赞赏。

【问题讨论】:

  • 你可以把它想象成一个参数。如果它为一个函数添加了const,则不会影响调用者。
  • 只有do_display 不能更改对象。 display可以。这里没有魔法,因为this 作为第一个(隐藏)参数传递。
  • 非 const 方法可以很好地更改对象,即使它们调用 const 方法。方法就像另一个带有隐藏“第一个”参数的函数。
  • 你通过值传递一个参数(指针的那个)所以你可以做任何你想做的事情
  • 谢谢,这是有道理的。我不确定“this”是隐式参数还是隐式返回的东西。

标签: c++ function pointers constants this


【解决方案1】:

转换display 中的非常量指针以便将其传递给do_display 会创建一个不同类型的新指针;它不会改变现有指针的类型。将this 传递给成员函数与将参数传递给非成员函数非常相似:

// A non-const member function receives `this` as a non-const pointer
Foo& display(Foo * this, std::ostream & os) {
    // Pass a copy of `this`, converted to `Foo const *`
    do_display(this, os);

    // The local `this` is still `Foo *`
    return *this;
}

// A const member function receives `this` as a const pointer
void do_display(Foo const * this, std::ostream & os) {os << this->contents;}

【讨论】:

  • 您是否体验过使用较新的编译器进行的复制?我目前主要使用老式的。
  • @Wolf:你不会“体验复制”,因为传递this 的机制是隐藏的。关键是,将它传递给另一个成员函数不会改变它在调用函数中的类型,就像传递普通参数不会改变任何局部变量的类型一样。
  • 好吧,我忘记了:this 指针无处不在,我什至不记得它必须传递给成员函数,在像 OP 的例子中,调用肯定会得到优化。
  • 不应该将do_display 的第一个参数声明为const Foo* this 而不是Foo const* this?我一直认为this 指针是“指向常量对象的指针”。
  • @jia103:两者是等价的。我通常将const 放在符合一致性的事物之后;但如果你愿意,你可以把它放在第一件事之前。
【解决方案2】:

在 C++ 中,const 访问通常只是一个编译时属性 [1],它被引入以简化对对象状态的控制。 [2]

do_display() 方法不会改变this 的任何内容,但它在其范围内将访问限制为只读。调用do_display()方法返回后,在display()方法的作用域内访问和之前一样是读写的。


[1] 这就是选择 cast const away 的原因,如果 constness 只是一个声明性,则可以认为这是安全的。

[2] 请参阅Effective C++: 55 Specific Ways to Improve Your Programs and Designs (3rd Edition): Scott Meyers 中的第 3 项或例如 Const Correctness - C++ Tutorials - Cprogramming.com

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-29
    • 2018-04-14
    • 2012-06-27
    • 2012-08-01
    • 2010-09-12
    • 1970-01-01
    相关资源
    最近更新 更多