下式给出:
#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();
}
所以B::func()
所做的就是致电A::func()
,有更好的方法吗?或者编译器在编译时直接调用A::func()
。
约束:
class A
创建线程,并由多个其他类使用。它是一个管理套接字/管道的全局IO类,所以我不相信任何类型的继承都会很好。
注意:如果这是一个google-able问题,请告诉我,因为我没有搜索什么。
答案 0 :(得分:1)
事实上,B.func()做了一些更微妙的事情:
它不调用A :: func而是调用GlobalA.func(),GlobalA是A类的实例。
所以这里GlobalA是一个单例(但以单一全局实例的非常“原始”方式表示)
因此,您将创建的B实例的数量,它们将始终调用相同的A实例(GlobalA)。
答案 1 :(得分:0)
这是一种常见模式:即网桥。 根据我的经验,它总是内联的(至少从版本4.3开始是g ++)。
请参阅Flexo的回答,在您发布的示例代码中确实调用了对A
成员函数的调用。
答案 2 :(得分:0)
从编译器中检出生成的程序集(我使用GCC 4.7 -O3):
A::func()
_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
B::func()
:
_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
它们是完全相同的 - 编译器在幕后为您免费做了一件事。在这种情况下,你的例子都在同一个翻译单元中,这使得编译器决定是否值得这样做是微不足道的。 (有些情况下最不可能是值得的,并且编译器将有一套非常好的启发式方法来帮助它找出对任何给定目标最佳的方法。)
如果他们在不同的翻译单元中,那么就变得非常困难。一些编译器仍将管理相同的优化,但不是全部。您当然可以通过将这些函数定义为inline
来确保它保留在每个案例的相同翻译单元中,这些函数允许您在头文件中指定它们。
故事的寓意是不要因为细微的细节而流连忘返 - 编写有意义且可维护的代码远更重要。