如何解决没有间接跳转的多态性?
| 几个月前,当我学习MIPS组装时,我突然想到了一个我忘记提的问题,所以我想现在就问: 没有间接跳转指令就可以实现多态吗?如果是这样,怎么办? (间接跳转是“跳转寄存器”指令,例如MIPS中的“ 0”或x86中的“ 1”。) 我想出的一种这样的解决方案是自我修改代码,但是我很好奇是否可以通过任何其他方式实现多态(以及OOP)。解决方法
最简单的答案是编写程序(和可能的汇编程序),以便所有方法调用都可以在运行时解决,从而无需查找表。我假设您正在谈论将子类传递给为超类设计的函数,因此不可能实现此优化。
我认为消除查找超出了您的问题范围,因此我将建议替换
jmp <reg>
指令(对不起,我只知道x86)。
您可以在存储器上执行call <mem>
地址(这不是您要怎么做)
它使用查找表?)
您可以在寄存器上执行call <reg>
(与jmp完全不同
,但确实回答了您的问题)
如果愿意的话,可以can5ѭ,但是
与ѭ2没什么不同
所有这些都有可能解决您的问题,但是都是一样的。我想这说明了我对为什么要执行自己的要求感到困惑。您必须具有某种方法来选择要调用的方法(vtable),以及某种将执行转移到该方法的方法(使用jmp
或call
)。
唯一可行的方法是摆弄用于指向执行链中下一个命令的寄存器(x86中的“ 9”)。能否还是应该是另一个问题。我想,如果您对体系结构非常了解,并且不担心更改它,可以这样做。
, 是
您可能需要考虑更改您的问题
考虑下面的C ++代码,其中ѭ10显然是多态的(是的,我没有删除对象):
class Base
{
public: int foo(){ return 1; }
};
class Derived: public Base
{
public: int foo(){ return 2; };
};
int main()
{
Base* b = new Derived();
return b->foo(); //Returns 1
}
由gcc生成的程序集是
main:
.LFB2:
pushq %rbp
.seh_pushreg %rbp
movq %rsp,%rbp
.seh_setframe %rbp,0
subq $48,%rsp
.seh_stackalloc 48
.seh_endprologue
call __main
movl $1,%ecx
call _Znwm
movq %rax,-8(%rbp)
movq -8(%rbp),%rax
movq %rax,%rcx
call _ZN4Base3fooEv
addq $48,%rsp
popq %rbp
ret
如您所见,没有间接跳转/调用。
那是因为多态性不是这里的重点(尽管有必要),虚方法才是重点。
然后答案就变成了
没有
如果通过间接跳转/调用,则表示使用运行时值来计算跳转/调用目标的每种技术(因此包括诸如ret
,call []
,call reg
,jr
,jalr
之类的东西)。
考虑这个来源
#include <iostream>
class Base
{
public: virtual int foo(){ return 1; }
};
class Derived: public Base
{
public: int foo(){ return 2; };
};
class Derived2: public Base
{
public: int foo(){ return 3; };
};
int main()
{
int a;
Base* b = 0; //don\'t remember the header for std::nullptr right now...
std::cin >> a;
if (a > 241)
b = new Derived();
else
b = new Derived2();
return b->foo(); //Returns what?
}
结果取决于用户输入,原型运行时值,因此必须是被调用的例程,并且没有静态地址可以执行。
请注意,在这种情况下,编译器可以使用跳转到具有静态地址的调用(因为调用了Derived2::foo
或Derived::foo
),但这通常是不可能的(您可能有多个没有源文件的目标文件,可能有别名指针,指针b
可以由外部库设置,依此类推)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。