有人可以向我解释为什么在类声明的末尾添加虚拟函数可以避免二进制不兼容吗?
如果我有:
class A
{
public:
virtual ~A();
virtual void someFuncA() = 0;
virtual void someFuncB() = 0;
virtual void other1() = 0;
private:
int someVal;
};
然后将该类声明修改为:
class A
{
public:
virtual ~A();
virtual void someFuncA() = 0;
virtual void someFuncB() = 0;
virtual void someFuncC() = 0;
virtual void other1() = 0;
private:
int someVal;
};
我从另一个 .so 中根据之前的声明编译得到了 coredump。但是如果我将 someFuncC() 放在类声明的末尾(在“int someVal”之后):
class A
{
public:
virtual ~A();
virtual void someFuncA() = 0;
virtual void someFuncB() = 0;
virtual void other1() = 0;
private:
int someVal;
public:
virtual void someFuncC() = 0;
};
我再也看不到核心转储了。有人能告诉我这是为什么吗?这个技巧总是有效吗?
附言。编译器是gcc,这可以与其他编译器一起使用吗?
From 另一个答案 https://stackoverflow.com/questions/1553382/1553407#1553407:
这是否会导致内存泄漏、擦除你的硬盘、让你怀孕、让讨厌的鼻恶魔在你的公寓里追着你,或者让一切正常工作而没有明显的问题,都是不确定的。对于一个编译器可能是这样,然后用另一个编译器进行更改,用新的编译器版本进行更改,每个新的编译进行更改,月相,您的心情,或者取决于最后一个阳光明媚时通过处理器的中微子数量下午。或者也可能不会。
所有这些,以及无限量的其他可能性都被放入一个术语中:未定义的行为:
只要远离它就可以了。
如果您知道特定编译器版本如何实现其功能,则可能会使其发挥作用。或者你可能不会。或者你可能认为它有效,但它会坏,但前提是坐在电脑前的人刚刚吃了一杯酸奶。
你有什么理由想让它发挥作用吗?
我认为它的工作方式/不工作方式是因为编译器按照声明虚拟函数的顺序创建虚拟表条目。如果你通过在其他函数之间放置一个虚函数来搞乱顺序,那么当有人调用时other1()
, 反而someFuncC()
被调用,可能带有错误的参数,但绝对是在错误的时刻。 (很高兴它立即崩溃。)
然而,这只是一种猜测,即使它是正确的,除非你的 gcc 版本附带了描述这一点的文档,否则不能保证明天它会这样工作即使使用相同的编译器版本.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)