以下4种调用另一个成员函数的方式有什么区别?
是否有一个好处导致一种方法是可取的?
void Object::trigger() {
(*this).triggerinner(10);
this->triggerinner(10);
triggerinner(10);
Object::triggerinner(10);
}
void Object::triggerinner(int x) {
std::cout << "trigger" << std::endl;
}
以下4种调用另一个成员函数的方式有什么区别?
是否有一个好处导致一种方法是可取的?
void Object::trigger() {
(*this).triggerinner(10);
this->triggerinner(10);
triggerinner(10);
Object::triggerinner(10);
}
void Object::triggerinner(int x) {
std::cout << "trigger" << std::endl;
}
前三个在非模板代码中基本相同。在模板成员函数中,前两个使名称查找依赖(因此编译器可以在依赖的基类中查找名称)。一般来说,越简单越好,所以大多数人喜欢第三种形式,除非需要依赖查找,在这种情况下他们会使用第二种。
第四种形式阻止虚拟分辨率。(实际上,它具有与上述相同的三种形式,即
this->Object::triggerinner(10)
等。)当您想要强制解析时使用它:被调用的函数将
Object
在 的基类中或中Object
,但从不在派生类中,即使函数是虚函数。这最常用于派生类中,用于在执行其他工作之前(或之后)调用基类实现:
void
Derived::func()
{
Base::func();
// Additional work here...
}
在成员函数之外,它还可以用于在没有对象时调用静态成员函数。
前两个是完全等价的。根据定义,(*p).thing
和p->thing
等价于任何指针。
第三种在这种情况下是等价的;但如果成员函数的名称被局部声明隐藏,则可能具有不同的含义。还有一些情况(函数是基类的成员,并且涉及模板)当此表单找不到函数时,在这种情况下您将不得不使用其他函数之一。
如果函数不是虚拟的,则第四个是等价的。如果它是虚拟的,那么这将强制对此类中可用的覆盖进行非虚拟调用,而不是最终覆盖。
最常用的是this->triggerinner(10);。它使用指针与表进行简单匹配的原因。
(*this).triggerinner(10);
这很丑陋,“->”是为了避免这样做。
this->triggerinner(10);
这很好,但this->
不是强制性的。如果您正在处理现有项目,请保持当前的编码风格。
triggerinner(10);
很好,与使用this->
.
Object::triggerinner(10);
将此用于静态方法。
我建议您使用它,triggerinner(10)
因为它简短明了。
this->triggerinner(10)
比其他人更好:
(*this).triggerinner(10)
因为它更具可读性更好。triggerinner(10)
,因为在这种情况下,您将不知道triggerinner()
是方法还是函数(然后具有不同的范围)。Object::triggerinner(10)
which 主要用于静态方法(但不仅如此)没有区别,除非你的编译器做了一些时髦的东西。尝试阅读由函数中的行生成的汇编语言,看看是否有任何差异,或者是否一遍又一遍地生成相同的指令块。
至于“最好的”或“最受欢迎的”,取决于您的个人喜好或在公司工作时,他们可能会强制执行某些编码标准,迫使您在每次做某事时都以特定的方式编写。