C++之运行时识别类型

运行时类型识别

目标

在我们只有一个指向基类的指针或者引用时确定一个对象的准确类型,虚函数机制可以帮助我们确定类是哪种类型,但是却远远不够。例如下面的代码:

class shape()
{
    shape();
    ~shape();
    virtual void draw() = 0;
}

从这个基类派生出三种不同的类:circle、square、triangle。我们调用其中类的draw方法,即使用一个shape()的指针来调用,任然被正确调用。


注意:RTTI与异常一样,依赖驻留在虚函数表中的类型信息。如果试图在一个没有虚函数的类上用RTTI,就得不到预期的结果。(可以进行测试一下)


RTTI的两种使用方法

(1)使用typeid关键字,注意这是一个关键字,像sizeof一样。
(2)“安全类型向下映射”,其实就是与“向上映射”相反。实现的方法:创建一个函数来试着将 shape*指派为一个 circle* (在本例中 ),检查执行过程中的数据类型。如果这个函数返回一个地址,则成功;如果返回 NULL,说明我们并没有一个circle *对象。C++的RTII的“安全类型向下映射”就是按照这种“试探映射”函数的格式。例子:

shape *sp = new circle;
circle *cp = dynamic_cast<circle*>sp
if(cp) cout<<"cast successful"

见下面例子

class shape
{
protected:
    static int count;
public:
shape()
{
    count++;
}
virtual ~shape() 
{
    count--;
}
virtual void draw() 
{

}
};

int shape::count = 0;

class rectage:public shape
{
void operator=(rectage &);
protected:
    static int count;
public:
rectage()
{
    count++;
}
~rectage()
{
    count--;
}
void draw()
{
    std::cout<<"~~~~~~"<<std::endl;
}
static int quatiy()
{
    return count;
}
};

int rectage::count = 0;

class circle:public shape
{
void operator=(rectage &);
protected:
    static int count;
public:
circle()
{
    count++;
}
~circle()
{
    count--;
}
void draw()
{
    std::cout<<"~~~~~~"<<std::endl;
}
static int quatiy()
{
    return count;
}
};

int circle::count = 0;

int main( int argc , char *argv[] )
{
std::vector<shape *> vVal;
time_t t;
srand((unsigned)time(&t));
const int mod = 12;
for ( int i = 0 ; i < rand()%12; ++i )
{
    vVal.push_back((shape *)(new rectage));
}
for ( int j = 0; j < rand()%12; ++j )
{
    vVal.push_back((shape *)(new circle));
}
int iRecCount = 0;
int iCirCount = 0;
for ( int u = 0; u < vVal.size() ; ++u)
{
    if ( dynamic_cast<rectage*>(vVal.at(u)))
    {
        iRecCount++;
    }

    if ( dynamic_cast<circle*>(vVal.at(u)))
    {
        iCirCount++;
    }
}

std::cout<<vVal.size()<<std::endl
    <<iRecCount <<" == "<<rectage::quatiy()<<std::endl
    <<iCirCount <<" == "<<circle::quatiy()<<"\n";


    return EXIT_SUCCESS;
}

总结

RIIT是C++的第二大特征(第一大特征是什么额?),上面只是大概的介绍了一下它,详细的使用见下面分解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 C++ 中使用 OpenCV 来识别条形码,可以使用 ZBar 库。ZBar 是一个流行的开源条形码扫描库,可以在 Linux、Windows 和 Mac OS X 等操作系统上运行。它支持多种条码类型,包括 EAN/UPC、Code 128、Code 39、Interleaved 2 of 5 等。 以下是使用 OpenCV 和 ZBar 库来识别条形码的步骤: 1. 安装 ZBar 库:可以从官方网站(http://zbar.sourceforge.net)下载最新的 ZBar 库并进行安装。 2. 配置 OpenCV:确保已经正确配置了 OpenCV 并且可以在 C++ 中使用。 3. 在 C++ 代码中引入 ZBar 库的头文件:`#include <zbar.h>` 4. 创建一个 ZBar 扫描器:`zbar::ImageScanner scanner;` 5. 加载图像并将其转换为灰度图像:`cv::Mat image = cv::imread("barcode.jpg", cv::IMREAD_GRAYSCALE);` 6. 将图像数据传递给 ZBar 扫描器:`zbar::Image zbarImage(image.cols, image.rows, "Y800", image.data, image.cols * image.rows);` 7. 扫描图像并获取结果:`scanner.scan(zbarImage);` 8. 遍历结果并输出条码数据:`for(zbar::Image::SymbolIterator symbol = zbarImage.symbol_begin(); symbol != zbarImage.symbol_end(); ++symbol) { std::cout << "Data: " << symbol->get_data() << std::endl; }` 完整的代码示例如下: ``` #include <opencv2/opencv.hpp> #include <zbar.h> int main(int argc, char** argv) { // 创建 ZBar 扫描器 zbar::ImageScanner scanner; // 加载图像并将其转换为灰度图像 cv::Mat image = cv::imread("barcode.jpg", cv::IMREAD_GRAYSCALE); // 将图像数据传递给 ZBar 扫描器 zbar::Image zbarImage(image.cols, image.rows, "Y800", image.data, image.cols * image.rows); // 扫描图像并获取结果 scanner.scan(zbarImage); // 遍历结果并输出条码数据 for(zbar::Image::SymbolIterator symbol = zbarImage.symbol_begin(); symbol != zbarImage.symbol_end(); ++symbol) { std::cout << "Data: " << symbol->get_data() << std::endl; } return 0; } ``` 注意,这只是一个简单的示例,实际应用中可能需要添加更多的错误处理和图像预处理步骤来提高识别的准确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值