【问题标题】:How and when to properly use *this pointer and argument matching?如何以及何时正确使用 *this 指针和参数匹配?
【发布时间】:2011-04-18 21:33:21
【问题描述】:

当我通过同事编写的代码时,在某些地方,他们使用:

this->doSomething(); //-->case A
doSomething(); //-->case B

事实上,我不确定 *this 指针的伟大用途...:(

另一个参数匹配问题:

obj.doOperation();  //-->case C
(&obj)->doOperation(); //-->case D

事实上,这两种情况都在执行所需的操作,是否只是让代码看起来更复杂的一种方式?

您对上述两个问题有何建议?什么时候使用它们合适?为什么?

【问题讨论】:

  • 为什么用 C 标记?术语“参数匹配”在这里做什么?
  • 当然你应该总是使用最复杂的方法:)
  • 我喜欢这句话:simply 一种让代码看起来更复杂(我的粗体字)的方法,或者说,“一种简单的方法编写复杂的代码。”哇!

标签: c++ dereference


【解决方案1】:

C 和 D 不同。如果doOperation 是虚拟的,case D 将执行虚拟调用,如果obj 不是引用,case C 将执行非虚拟调用。然而,这假设 operator&operator-> 没有被重载。

我倾向于使用 A 而不是 B,因为可能有一个本地 doSomething 标识符。在模板代码内部,情况可能会变得更糟(尽管我现在无法提供精确的示例)。这是一个好习惯。

【讨论】:

  • "如果 obj 不是引用,则进行非虚拟调用" —嗯....如果 obj 不是引用,虚拟和非虚拟调用之间会有区别吗?不是解析成同一个函数吗?
  • @ybungalobill:不。如果objC 类的变量,则obj.doSomething() 将始终解析为obj.C::doSomething()。如果obj 是引用,它将执行虚拟调度。
  • 如果 obj 是一个变量,虚拟调用 (&obj)->doSomething() 将解析为与非虚拟调用 obj.doSomething() 相同的函数,但我猜一个调用是虚拟的,另一个是非虚​​拟的:)
【解决方案2】:

情况 B 和 C 总是合适的方法。情况 A 和 D 是等价的,没有什么不同。

有几个例外:

  • 如果类有一个重载的 operator& 会做一些令人惊讶的事情,那么案例 D 可以做一些与 C 不同的事情。实际上不建议使用这样做的类,因为这会令人困惑。
  • 如果有一个局部变量doSomething(或局部范围内的其他名称),那么 A 将指代与 B 不同的 doSomething。同样不建议让自己陷入这样的情况,最好给不同的东西起不同的名字。

【讨论】:

    【解决方案3】:

    这不是对您问题的回答,而是注意两个片段可能会做不同的事情:

    namespace B { void doSomething() {} }
    
    struct A {    
        void f()
        {
            using B::doSomething;
            this->doSomething(); // call A::doSomething
            doSomething(); // calls B::doSomething
        }
    
        int a;
        void g(int a)
        {
            this->a = a; // assigns argument to member
        }
    
        A* operator & () { return this; }
        void doOperation() {}
        void doSomething() {}
    };
    
    void g(A &obj)
    {
        obj.doOperation();  // calls A::doOperation directly
        (&obj)->doOperation(); // calls A::operator & first
    }
    

    【讨论】:

    • 如果你重载了operator->,它也会在第二个例子中调用它!
    • 前者是反对使用using的可能论据!
    • @Oli:“如果你超载了......”不。如果我写obj->doOperation(),它将被调用。 “前者是……”这是一个非常弱的论点。
    • operator-> 的好点子。关于using,我想说这是一个相当规范的论点;弄乱本地命名空间,然后导致混淆,而不是明确的消歧(即B::doSomething())。
    • @Oli:同意这种情况,但一般不反对使用using
    猜你喜欢
    • 1970-01-01
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 2012-02-27
    • 2012-02-20
    • 2016-12-25
    • 1970-01-01
    相关资源
    最近更新 更多