识别标识符为的派生类不起作用

Recognize derived class with identifier not working

本文关键字:不起作用 派生 标识符 识别      更新时间:2023-10-16

我正在尝试使用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 << "answerswer = " << 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指令跳到主函数的末尾,因为设置了零标记。这是怎么回事?是我遗漏了什么,还是编译器(目标为x86_64-linux-gnug++ 4.9.2)生成了错误的指令?

编译时始终启用警告。您的问题是操作顺序问题,其中&的优先级低于==,因此您需要:

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)
                        ^
       (                      )