我想寫一些代碼,我可以在堆棧上創建一個基類,並通過調用該基類來修改vtable。MSVC內嵌虛函數調用時,它不應該
class Base
{
public:
void initAs(int version);
virtual int foo() { assert(false); return 0; }
};
class A : public Base
{
public:
virtual int foo() { return 1; }
};
void Base::initAs(int version)
{
switch(version)
{
case 1:
new (this) A();
break;
default:
break;
}
}
int main()
{
Base x;
int version = 1;
x.initAs(version);
int v = x.foo();
assert(v == 1);
return 0;
}
我運行到),其中x.foo()內聯調用基地:: foo的(問題,而不是A :: foo的()。我檢查了反彙編,並沒有vtable解決方案。編譯器決定內聯該虛函數,即使它應該能夠看到指向x的內存正在被修改。我怎樣才能停止編譯器(MSVC 14)內聯函數調用x.foo()?
編輯: 我不是在尋找意見或答案如何undefined這種行爲是。據我所知,我應該期望x.foo()應該通過整個虛擬函數調用堆棧,因爲它被標記爲虛函數,並且我無法完全限定函數名(akaxBase :: foo( ))。我在代碼中有其他地方可以工作:
class Container
{
private:
Base x;
Container();
void foo();
};
Container::Container() { x.initAs(1); }
void Container::foo() { assert(x.foo() == 1; } // This call is correct A::foo()
編譯器中的差異在哪裏,我該如何關閉它?
這是未定義的行爲。 –
編譯器正在做它應該做的事情。你的代碼有未定義的行爲,你的期望是無效的。 –
這標記爲未定義的行爲在哪裏?你能給我一個鏈接嗎? –