C++で一意の識別子番号を使用して派生クラス用の汎用インターフェイスを作成しようとしています。これは私のコードは次のようになります識別子が正しくない派生クラスを認識します
は(あなたはそれをコンパイルするには、少なくともC++ 11が必要):
#include <iostream>
#include <memory>
class Base
{
protected:
int ident;
Base(int newIdent) : ident(newIdent) { }
public:
Base() : ident(0x01) { }
virtual ~Base() { } //needed to make class polymorphic
int getIdent() { return ident; }
};
class Derived : public Base
{
protected:
int answer;
Derived(int newIdent, int newAnswer) : Base(newIdent), answer(newAnswer) { }
public:
Derived(int newAnswer) : Base(0x11), answer(newAnswer) { }
int getAnswer() { return answer; }
};
int main()
{
std::shared_ptr<Base> bPtr = std::make_shared<Derived>(Derived(42));
std::cout << "ident = 0x" << std::hex << bPtr->getIdent() << std::dec << "\n";
if(bPtr->getIdent() & 0xF0 == 1)
{
std::shared_ptr<Derived> dPtr = std::dynamic_pointer_cast<Derived>(bPtr);
std::cout << "answer = " << dPtr->getAnswer() << "\n";
}
return 0;
}
はもちろん、あなたがプログラムの出力ident = 0x11
とanswer = 42
が、それがないことを期待してくださいなぜなら、それは通常、ident = 0x11
行の後に存在するからです。私はまた、GDBといくつかの検査と主な機能に重要なif
条件チェックの分解が問題を確認しました:
0x0000000000400f46 <+196>: call 0x401496 <std::__shared_ptr<Base, (__gnu_cxx::_Lock_policy)2>::operator->() const>
0x0000000000400f4b <+201>: mov rdi,rax
0x0000000000400f4e <+204>: call 0x4012bc <Base::getIdent()>
0x0000000000400f53 <+209>: mov eax,0x0
0x0000000000400f58 <+214>: test al,al
0x0000000000400f5a <+216>: je 0x400fb7 <main()+309>
あなたは*0x400f53
で破断すると、RAXがきれいに正しい値(0x11
)を保持しますが、以下の命令はraxにゼロを上書きするだけです。test
はゼロフラグを設定し、je
命令はゼロフラグが設定されているため、メイン関数の最後にジャンプします。ここで何が起こっているのですか?私は何かが欠けているか、間違った指示を生成するコンパイラ(g++ 4.9.2
x86_64-linux-gnu
ターゲット)ですか?
'のstd :: make_shared(派生(42))'なぜ余分なコピー? –
「終了します」と定義します。 –
@LightnessRacesinOrbit正常に存在します。 – sigalor