识别标识符不工作的派生 class
Recognize derived class with identifier not working
我正在尝试使用 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
目标)生成了错误的指令?
始终在启用警告的情况下进行编译。您的问题是 &
的优先级低于 ==
的操作顺序问题,因此您需要:
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)
~~~~~^~~~
或者来自 clang 的这个:
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)
^
( )
我正在尝试使用 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
目标)生成了错误的指令?
始终在启用警告的情况下进行编译。您的问题是 &
的优先级低于 ==
的操作顺序问题,因此您需要:
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)
~~~~~^~~~
或者来自 clang 的这个:
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)
^
( )