【问题标题】:When should I use this->functionname() over classname::functionname() for calling member functions?我什么时候应该使用 this->functionname() 而不是 classname::functionname() 来调用成员函数?
【发布时间】:2016-11-28 13:08:23
【问题描述】:

我一直在查看一些示例代码,它们同时使用 this->functionname()classname::functionname() 来调用同一类中的函数。

这两种方法真的有区别吗?

另外,这些方法和仅仅使用 functionname() 调用函数有区别吗?

谢谢。

【问题讨论】:

  • 这个问题的答案是这个新文档的好候选人。

标签: c++ oop namespaces this


【解决方案1】:

在 C++ 中,事情并没有你想象的那么简单。

调用成员函数有三种方式。

  1. 只需调用函数:foo();
  2. 拨打this:this->foo();
  3. 使用类名:classname::f();

数字#1 和#2 是等价的,有些人更喜欢#2,因为它更清楚地表明这是一个成员函数而不是全局函数(这些人是少数)。

#3 与#1 和#2 是否不同,取决于调用的函数是否为虚函数。如果它是非虚拟的,则没有区别。如果它虚拟并且这个函数有一个更派生的覆盖,那么#1和#2将调用派生函数,而#3将调用这个类中存在的覆盖(或者如果此类中没有覆盖,则为最接近的超类)。

上一段的例外是调用站点位于构造函数或析构函数中。在这种情况下,即使函数是虚拟的,#1 和 #2 的行为也会与 #3 相同(调用 this 中的覆盖,或最近的超类)。

此外,如果函数是static,则#2 无效,从类内调用时#1 和#3 是等效的,但从类外调用时需要#3。

希望我没有错过任何东西:)

我错过的事情:

  • 如果函数被调用函数内部重新声明的全局隐藏,则可能需要this。见@Dutow's answer
  • this 在处理two phase lookup(涉及模板时)时很有用。感谢@Alejandro 的评论。
  • 我猜想使用 using 可能会在水里扔更多的泥浆,但我现在懒得去研究它(买错者)。

确实,没有想象中那么简单……

【讨论】:

  • 您也可以提出 this 在某些情况下也需要正确的 two phase lookup 的论点
【解决方案2】:

通常?他们是一样的。但根据上下文,它们可能意味着不同的东西。

例如,考虑以下极端示例(不要在实际项目中这样做!):

void f() { std::cout << "f" << std::endl; }

class Cl {
public:
    void f() { std::cout << "Cl::f" << std::endl;  }
    void g() { 
        struct Cl {
            static void f() { std::cout << "inside Cl::f" << std::endl; }
        };
        void f();  

        f(); 
        Cl::f();
        this->f();
    }
};

int main()
{
    Cl a;
    a.g();

    return 0;

}

这里,全局f的声明隐藏了成员方法f,导致程序输出f而不是Cl::f

本地的struct Cl 也隐藏了它自己的类型名,导致Cl::f() 调用它的静态f 方法。

仅显式调用this-&gt;f() 会导致调用Cl::f

当您想在使用继承和覆盖虚拟方法时调用父类中的方法时,也通常使用带有类型名的变体 - 但从技术上讲,这不是同一个类。

【讨论】:

  • 直到你可以在一个函数中声明一个函数(我认为我的回答很详尽......)
  • 你先生,是邪恶的!做得好(我在我的参考了你的答案)。
【解决方案3】:

我认为使用它的一个原因是在这种情况下。例如

class A
{
public:
    void foo() { this->doFoo(); } //equivalent to just doFoo();
    void foo2() { Abstract::doFoo(); }
private:
    virtual void doFoo() { /* do stuff */ }
};

在 sn-p 中调用foo 时,它将调用最派生类中的doFoo。当调用foo2 时,它总是会调用基本实现,即使它被覆盖了。

【讨论】:

    猜你喜欢
    • 2019-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 2016-08-09
    • 2011-12-26
    相关资源
    最近更新 更多