私は、かなり大きなプロジェクトを複数のインターフェースと実装で持っています。 コードはg ++を使ってLinux環境で実装されています(5.4と思います)。コードをWindowsに移植し、VS15(MSVC v140)で実行した後、キャストされたポインタにアクセスしようとした後にアクセス違反が発生しました。msvcのC++アクセス違反ですが、多重継承とキャストのためのgccではありません
これは以下のコードで継承階層である:実際のコードで
A
/\
virtual / \
/ |
B |
| | virtual
C |
| |
\ /
\ /
D
継承のデザインはので、これは私がA
から継承方法である理由で選択しないでください以上のクラスが含まれています。 私はコードを絞り込んで必要なものだけを提示しました。 GCCと
次が実行され、プリントfoo called
二回(Live demo on rextester)が、アクセス違反でfoo
クラッシュへの2回目の呼び出しにMSVCで(Live demo on rextester)
#include <iostream>
class A{};
class B : public virtual A{};
class C : public B
{
public:
virtual void foo() = 0;
};
class D : public virtual A, public C
{
public:
bool convert(int id, B** ext)
{
if (id == 1)
{
*ext = (C*)this;
return true;
}
if (id == 42)
{
C** pp_ext = (C**)(ext);
*pp_ext = (C*)this;
return true;
}
return false;
}
void foo() override
{
std::cout << "foo called" << std::endl;
}
};
int main()
{
D s;
C* foo_ext = nullptr;
s.convert(42, (B**)&foo_ext);
foo_ext->foo();
foo_ext = nullptr;
s.convert(1, (B**)&foo_ext);
foo_ext->foo();
return 0;
}
まず - 私は*ext = (C*)this;
変換に根本的な誤りが足りませんか?
第2 - 2つのコンパイラでこのコードが異なるのはなぜですか?
EDIT:
このコードは、ポインタへのポインタ、ポインタを使用し、(ABI準拠のインタフェースであるそのうちの一つ)正当な理由のために、この継承を使用して構築されています。
dynamic_cast
この場合の動作は変更されません。*ext = (C*)this;
の後にstatic_cast<C*>(*ext)->foo();
を呼び出すと、fooが呼び出されますが、convert
から戻って失敗します。これは私がすでに理解しているもので、これが42
の解決策が(良い?)解決策であることを私に理解させたものです。
Cスタイルのキャストとあまりにも多くの星を使用して停止します。 – LogicStuff
http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used – LogicStuff
これはこれを断る正当な理由ではありません質問。 – ZivS