C++ 只调用其他类成员的类成员?
鉴于:C++ 只调用其他类成员的类成员?,c++,C++,鉴于: #包括 甲级 { B级朋友; 私人: void func(); }GlobalA; void A::func() { printf(“A::func()”; } B类 { 公众: void func(); }; void B::func() { GlobalA.func(); } int main() { B B; b、 func(); getchar(); } 所以实际上B::func()所做的就是调用A::func(),有更好的方法吗?或者编译器在编译时直接调用A::func()
#包括
甲级
{
B级朋友;
私人:
void func();
}GlobalA;
void A::func()
{
printf(“A::func()”;
}
B类
{
公众:
void func();
};
void B::func()
{
GlobalA.func();
}
int main()
{
B B;
b、 func();
getchar();
}
所以实际上B::func()
所做的就是调用A::func()
,有更好的方法吗?或者编译器在编译时直接调用A::func()
限制条件:
class A
创建线程并由多个其他类使用。它是一个管理套接字/管道的全局IO类,所以我不相信任何类型的继承都会成功
注意:如果这是一个可以通过谷歌搜索的问题,请告诉我,因为我不知道该搜索什么。这是一个常见的模式:即桥。 根据我的经验,它总是内联的(至少从版本4.3开始是g++的)
参见Flexo的回答,对
A
成员函数的调用确实内联在您发布的示例代码中。查看编译器生成的程序集(我使用了GCC 4.7-O3):
对于A::func()
和B::func()
:
它们是一样的——编译器在幕后免费为您做了聪明的事情。在本例中,您的示例都在同一个翻译单元中,这使得编译器很难决定是否值得这样做。(在某些情况下,它很可能不值得,编译器将有一组非常好的启发式方法来帮助它找出对任何给定目标最好的方法)
如果他们在不同的翻译单位,那就很难做到了。一些编译器仍将管理相同的优化,但不是全部优化。当然,您可以通过将这样的函数定义为inline
,从而在头文件中指定它们,从而确保它在每种情况下都保持在相同的翻译单元中
这个故事的寓意是不要为琐碎的细节操心——编写有意义且可维护的代码要重要得多。事实上,B.func()做了一些更微妙的事情:
它不调用A::func,而是调用GlobalA.func(),GlobalA是类A的实例
所以这里GlobalA是一个单例(但以一个非常“原始”的方式表示为单个全局实例)
因此,无论您创建多少个B实例,它们都会调用同一个A实例(GlobalA)。看看这个dissasembly,它可以是内联的,是的。请通过正确缩进所有内容来修复此帖子的格式。不要使用标签。这读起来很烦人。@user1204406:我通常在web中键入三个空格进行缩进。当然,这取决于编译器。虽然我认为可以肯定地说,任何一个下降编译器都会在这样一个简单的情况下内联。我不知道这是如何回答这个问题的。我通过发现导致问题本身的分析中的一些错误来回答这个问题。B::func不调用a::func,而是调用GlobalA.func,这是一个很大的区别,应该可以帮助您改进分析
#include <stdio.h>
class A
{
friend class B;
private:
void func();
} GlobalA;
void A::func()
{
printf("A::func()");
}
class B
{
public:
void func();
};
void B::func()
{
GlobalA.func();
}
int main()
{
B b;
b.func();
getchar();
}
_ZN1A4funcEv:
.LFB31:
.cfi_startproc
subl $28, %esp
.cfi_def_cfa_offset 32
movl $.LC0, 4(%esp)
movl $1, (%esp)
call __printf_chk
addl $28, %esp
.cfi_def_cfa_offset 4
ret
.cfi_endproc
_ZN1B4funcEv:
.LFB32:
.cfi_startproc
subl $28, %esp
.cfi_def_cfa_offset 32
movl $.LC0, 4(%esp)
movl $1, (%esp)
call __printf_chk
addl $28, %esp
.cfi_def_cfa_offset 4
ret
.cfi_endproc