C++ 本手册是否合法/可行?
对于我的一个项目,我最终需要使用我的第一个多态类(std::cout除外) 我正在研究如何确保至少在某些情况下我有100%的设备化呼叫 该守则是否合法可行 动态播放的速度有多慢?如果我在构造函数中支付一次,那么我将始终能够直接使用classC++ 本手册是否合法/可行?,c++,devirtualization,C++,Devirtualization,对于我的一个项目,我最终需要使用我的第一个多态类(std::cout除外) 我正在研究如何确保至少在某些情况下我有100%的设备化呼叫 该守则是否合法可行 动态播放的速度有多慢?如果我在构造函数中支付一次,那么我将始终能够直接使用classB,所以这听起来是一个好的实践 在那之后,C样式转换是否会很快,或者我必须存储指向B的指针 struct A{ virtual void x(); }; struct B : A{ void x() override; }; struct
B
,所以这听起来是一个好的实践
在那之后,C样式转换是否会很快,或者我必须存储指向B
的指针
struct A{
virtual void x();
};
struct B : A{
void x() override;
};
struct X{
A *a;
bool fB;
X(A &a) : a(&a), fB( dynamic_cast<B *>(&a) ){}
void f(){
if (fB){
((B*)a)->x();
}else{
a->x();
}
}
};
void fn(A &a){
X x(a);
x.f();
}
int main(){
B b;
X x(b);
x.f();
}
结构A{
虚空x();
};
结构B:A{
void x()覆盖;
};
结构X{
A*A;
布尔fB;
X(A&A):A(&A),fB(dynamic_cast(&A)){}
void f(){
如果(fB){
((B*)a)->x();
}否则{
a->x();
}
}
};
无效fn(A&A){
X(a);
x、 f();
}
int main(){
B B;
X(b);
x、 f();
}
您尝试将虚拟呼叫更改为分支 我已经不确定它是否更快 但更糟糕的是,您没有删除虚拟调用,因为
B
可以有子child,您至少必须使void B::x()成为final
以允许编译器对调用进行虚拟化
如果编译器可以访问具体类型(和代码),如
main
中所述,它可能能够单独对调用进行设备化。您尝试将虚拟调用更改为分支
我已经不确定它是否更快
但更糟糕的是,您没有删除虚拟调用,因为B
可以有子child,您至少必须使void B::x()成为final
以允许编译器对调用进行虚拟化
如果编译器可以访问具体类型(和代码),如
main
中所述,它可能能够单独对调用进行设备化。对于您现有的代码,我实际上希望您的编译器优化掉If语句和cast,因为这会使代码变得更加复杂
从编译器的角度来看,您的代码库可能如下所示:
struct A{
virtual void x();
};
struct B : A{
void x() override;
};
struct C : B{
void x() override;
};
因此,当is看到您的强制转换和函数调用时:static\u cast(a)->x()
它仍然必须访问与调用a->x()
时相同的虚拟表,因为可能存在潜在的类C。
(请注意,我使用静态类型转换,因为c样式转换是bug的来源)
如果您想直接调用B,最好将方法或类设置为final。另一个好方法是使用概要文件引导优化,在这种情况下,他们经常比较vtable指针
回答你的附带问题
- 守则合法吗?是的
- 这是否可行?是的,考虑到上面的评论
- 动态_的速度有多慢?慢,我会争辩说要为此写一个好的基准,然而,我不知道如何做到这一点,使之成为现实
- 这是好的做法吗?不,这会降低多态性的可用性
- 静态施法速度快吗?是的,速度很快,在这种特殊情况下,不需要任何说明。与bool相比,在复杂继承的特定情况下,存储指向B的指针可以提高性能。如果需要额外的内存,也可能导致性能下降。通过在可执行文件中增加额外的程序集,可以实现另一种减少
哦,如果你想知道它的实际汇编代码是什么,你可以用你现有的代码在上进行实验,我实际上希望你的编译器优化掉if语句和cast,因为这会使代码变得更加复杂 从编译器的角度来看,您的代码库可能如下所示:
struct A{
virtual void x();
};
struct B : A{
void x() override;
};
struct C : B{
void x() override;
};
因此,当is看到您的强制转换和函数调用时:static\u cast(a)->x()
它仍然必须访问与调用a->x()
时相同的虚拟表,因为可能存在潜在的类C。
(请注意,我使用静态类型转换,因为c样式转换是bug的来源)
如果您想直接调用B,最好将方法或类设置为final。另一个好方法是使用概要文件引导优化,在这种情况下,他们经常比较vtable指针
回答你的附带问题
- 守则合法吗?是的
- 这是否可行?是的,考虑到上面的评论
- 动态_的速度有多慢?慢,我会争辩说要为此写一个好的基准,然而,我不知道如何做到这一点,使之成为现实
- 这是好的做法吗?不,这会降低多态性的可用性
- 静态施法速度快吗?是的,速度很快,在这种特殊情况下,不需要任何说明。与bool相比,在复杂继承的特定情况下,存储指向B的指针可以提高性能。如果需要额外的内存,也可能导致性能下降。通过在可执行文件中增加额外的程序集,可以实现另一种减少
哦,如果你想知道它的实际汇编代码是什么,你可以在上进行实验普利茅斯的好处是虚拟函数将被解析并自动调用到正确的类上。因此,您不需要
fB
或动态强制转换。只要void f(){a->x();}
就可以了。作为一个一般提示:所有的C风格铸造都应该被视为你做错了什么的危险信号。你似乎没有抓住要点。在循环中调用非虚拟化的虚拟函数,每次都会解析虚拟函数。因为我想执行