2016-05-16 14 views
1

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 = 0x11answer = 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.2x86_64-linux-gnuターゲット)ですか?

+1

'のstd :: make_shared (派生(42))'なぜ余分なコピー? –

+0

「終了します」と定義します。 –

+0

@LightnessRacesinOrbit正常に存在します。 – sigalor

答えて

5

常に警告が有効な状態でコンパイルしてください。あなたの問題は&==よりも低い優先順位を持って業務上の問題のためであるので、あなたが必要とする:

if ((bPtr->getIdent() & 0xF0) == 1) 

あなたは間違ったことに対して比較している、その後が、あなたのよう本当にがしたい:

if ((bPtr->getIdent() & 0xF0) == 0x10) 
この場合

、あなたは、GCCからこれを見るでしょう:

main.cpp:32:32: warning: suggest parentheses around comparison in operand of '&' [-Wparentheses] 
    if(bPtr->getIdent() & 0xF0 == 1) 
          ~~~~~^~~~ 

またはこの打ち鳴らすから:

main.cpp:32:25: warning: & has lower precedence than ==; == will be evaluated first [-Wparentheses] 
    if(bPtr->getIdent() & 0xF0 == 1) 
         ^~~~~~~~~~~ 
main.cpp:32:25: note: place parentheses around the '==' expression to silence this warning 
    if(bPtr->getIdent() & 0xF0 == 1) 
         ^
          (  ) 
main.cpp:32:25: note: place parentheses around the & expression to evaluate it first 
    if(bPtr->getIdent() & 0xF0 == 1) 
         ^
     (     ) 
+0

これは誤解を招くような誤解を招くような "最初に評価される"という用語を使用することです。 –

+0

http://kera.name/articles/2013/10/nobody-writes-testcases-any-more/ –

+0

@LightnessRacesinOrbitなぜあなたはブログのテキストを陰にしていましたか... – Barry

関連する問題