CPlusPlus - #018 RTTI(运行时类型识别)

RTTI(运行时类型识别)

1 目标

本文的目的是学习RTTI(运行时类型识别)。

2 示例代码

RTTI(运行时类型识别)在 C++ 中用于在运行时识别对象的类型。RTTI 提供了两个主要的操作符:dynamic_cast 和 typeid。

2.1 使用 dynamic_cast 进行类型转换

#include <iostream>
#include <typeinfo>

class Base {
public:
    virtual ~Base() = default; // 虚析构函数,使 Base 成为多态类
};

class Derived1 : public Base {
public:
    void show() {
        std::cout << "这是 Derived1 类" << std::endl;
    }
};

class Derived2 : public Base {
public:
    void display() {
        std::cout << "这是 Derived2 类" << std::endl;
    }
};

void checkType(Base* base) {
    if (Derived1* d1 = dynamic_cast<Derived1*>(base)) {
        d1->show();
    } else if (Derived2* d2 = dynamic_cast<Derived2*>(base)) {
        d2->display();
    } else {
        std::cout << "无法识别的类型" << std::endl;
    }
}

int main() {
    Base* b1 = new Derived1();
    Base* b2 = new Derived2();
    Base* b3 = new Base();

    checkType(b1); // 输出:这是 Derived1 类
    checkType(b2); // 输出:这是 Derived2 类
    checkType(b3); // 输出:无法识别的类型

    delete b1;
    delete b2;
    delete b3;

    return 0;
}

2.2 使用 typeid 进行类型识别

#include <iostream>
#include <typeinfo>

class Base {
public:
    virtual ~Base() = default; // 虚析构函数,使 Base 成为多态类
};

class Derived1 : public Base {};

class Derived2 : public Base {};

void printTypeInfo(Base* base) {
    std::cout << "对象的实际类型是: " << typeid(*base).name() << std::endl;
}

int main() {
    Base* b1 = new Derived1();
    Base* b2 = new Derived2();
    Base* b3 = new Base();

    printTypeInfo(b1); // 输出:对象的实际类型是: 7Derived1(具体输出取决于编译器)
    printTypeInfo(b2); // 输出:对象的实际类型是: 7Derived2(具体输出取决于编译器)
    printTypeInfo(b3); // 输出:对象的实际类型是: 4Base(具体输出取决于编译器)

    delete b1;
    delete b2;
    delete b3;

    return 0;
}

3 总结

RTTI 使得在运行时处理多态类层次结构中的对象类型变得更加灵活和安全。

  • dynamic_cast:用于安全地向下转换指针或引用,确保类型转换是有效的。
  • typeid:用于获取对象的实际类型信息,可以用于调试和日志记录。
  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SECS-II(SEMI Equipment Communications Standard 2)是一种半导体制造设备之间通信的标准。SECS-II消息通常采用二进制格式进行传输,需要进行打包和拆包。 SECS-II消息的打包和拆包可以使用C++语言实现。具体实现方式如下: 1. SECS-II消息的打包 SECS-II消息的打包过程需要按照一定的格式进行组装,包括消息头、消息体和消息尾。其中,消息头和消息尾是固定的格式,消息体则根据消息内容的不同而变化。 以S1F1为例,消息头格式如下: ``` <header><device id><stream><function><transaction id><system byte> ``` 其中,`<header>`和`<device id>`是固定的值,`<stream>`和`<function>`表示消息类型,`<transaction id>`为事务ID,`<system byte>`为系统字节。 下面是一个示例代码,用来打包一个S1F1消息: ```c++ void packS1F1Message(int transactionId, std::string data, unsigned char* buffer, int bufferSize) { // 检查缓冲区大小是否足够 if (bufferSize < S1F1_MESSAGE_SIZE) { return; } // 组装消息头 buffer[0] = 0x00; buffer[1] = 0xFF; buffer[2] = 0x00; buffer[3] = 0x00; buffer[4] = (transactionId >> 8) & 0xFF; buffer[5] = transactionId & 0xFF; buffer[6] = 0x00; buffer[7] = 0x00; // 组装消息体 int dataLength = data.length(); buffer[8] = (dataLength >> 8) & 0xFF; buffer[9] = dataLength & 0xFF; memcpy(buffer + 10, data.c_str(), dataLength); // 组装消息尾 buffer[S1F1_MESSAGE_SIZE - 2] = 0x0D; buffer[S1F1_MESSAGE_SIZE - 1] = 0x0A; } ``` 2. SECS-II消息的拆包 SECS-II消息的拆包过程需要解析消息头、消息体和消息尾,并根据消息类型进行相应的处理。 以S1F1为例,消息头和消息尾的解析方法如下: ```c++ bool unpackS1F1Header(unsigned char* buffer, int bufferSize, int& transactionId) { // 检查缓冲区大小是否足够 if (bufferSize < S1F1_MESSAGE_SIZE) { return false; } // 解析消息头 if (buffer[0] != 0x00 || buffer[1] != 0xFF || buffer[6] != 0x00 || buffer[7] != 0x00) { return false; } // 解析事务ID transactionId = (buffer[4] << 8) + buffer[5]; return true; } bool unpackS1F1Footer(unsigned char* buffer, int bufferSize) { // 检查缓冲区大小是否足够 if (bufferSize < S1F1_MESSAGE_SIZE) { return false; } // 解析消息尾 if (buffer[S1F1_MESSAGE_SIZE - 2] != 0x0D || buffer[S1F1_MESSAGE_SIZE - 1] != 0x0A) { return false; } return true; } ``` 消息体的解析则需要根据消息类型进行相应的处理。例如,如果是S1F1消息,可以使用以下代码解析消息体: ```c++ bool unpackS1F1Data(unsigned char* buffer, int bufferSize, std::string& data) { // 检查缓冲区大小是否足够 if (bufferSize < S1F1_MESSAGE_SIZE) { return false; } // 解析消息体 int dataLength = (buffer[8] << 8) + buffer[9]; char* dataBuffer = new char[dataLength + 1]; memcpy(dataBuffer, buffer + 10, dataLength); dataBuffer[dataLength] = '\0'; data = std::string(dataBuffer); delete[] dataBuffer; return true; } ``` 以上是SECS-II消息的打包和拆包的基本代码实现,具体实现方式还需要根据具体的消息类型进行调整和修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

满天飞飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值