Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
关于为指向运行时确定的许多结构之一的指针构造类的建议 我正在编写一个位图(BPM)解析器,以在我学习的时候练习C++。然而,版本上有许多不同的图像标题,我碰到了一堵墙,围绕着如何实现这一点,我觉得这是一种避免了许多检查的方式,而且很优雅。你能就以下几种方法给我一些建议或建议其他方法吗_C++_Pointers_Struct_Encoding_Bmp - Fatal编程技术网

关于为指向运行时确定的许多结构之一的指针构造类的建议 我正在编写一个位图(BPM)解析器,以在我学习的时候练习C++。然而,版本上有许多不同的图像标题,我碰到了一堵墙,围绕着如何实现这一点,我觉得这是一种避免了许多检查的方式,而且很优雅。你能就以下几种方法给我一些建议或建议其他方法吗

关于为指向运行时确定的许多结构之一的指针构造类的建议 我正在编写一个位图(BPM)解析器,以在我学习的时候练习C++。然而,版本上有许多不同的图像标题,我碰到了一堵墙,围绕着如何实现这一点,我觉得这是一种避免了许多检查的方式,而且很优雅。你能就以下几种方法给我一些建议或建议其他方法吗,c++,pointers,struct,encoding,bmp,C++,Pointers,Struct,Encoding,Bmp,以下是我想到的方法。我遇到问题的主要原因是我想使用memcpy来避免单独复制每个字段。结构之间唯一一致的是定义头/结构大小的前4个字节 在类中使用多个指针。在初始化时将每个参数设置为nullptr。然后使用一个reinterpret\u cast来确定第一次解析文件时要使用的头。从那时起,检查哪个指针不是nullptr,以确定使用哪个指针 在执行获取或设置标题中的值的操作时,使用void ptr并使用重新解释\u cast。也许不是最好的选择,但它就在那里 创建一个(我不确定我是否完全理解)。将

以下是我想到的方法。我遇到问题的主要原因是我想使用
memcpy
来避免单独复制每个字段。结构之间唯一一致的是定义头/结构大小的前4个字节

  • 在类中使用多个指针。在初始化时将每个参数设置为nullptr。然后使用一个
    reinterpret\u cast
    来确定第一次解析文件时要使用的头。从那时起,检查哪个指针不是nullptr,以确定使用哪个指针

  • 在执行获取或设置标题中的值的操作时,使用void ptr并使用
    重新解释\u cast
    。也许不是最好的选择,但它就在那里

  • 创建一个(我不确定我是否完全理解)。将允许继承结构。我不确定这是否能在
    memcpy
    中顺利运行,因为据我所知,使用虚拟方法会在结构的开头添加一个不可见的指针,它会使用未修改的缓冲区直接将其覆盖到结构中而中断。(如果我错了,请告诉我)

  • 目前正在尝试一种方法。这是我的头文件

    \ifndef位图\u包括
    #定义位图\u H\u包含
    #包括
    #包括
    #包括
    #包括
    枚举标题
    {
    文件=14,
    核心=12,
    InfoV1=40,
    OS2=64,
    InfoV4=108,
    InfoV5=124,
    };
    枚举信息压缩方法
    {
    //为简洁起见省略
    };
    枚举半色调算法
    {
    //为简洁起见省略
    };
    结构文件头
    {
    //为简洁起见省略,第一个标头始终为14字节
    };
    结构核心头
    {
    uint32_t收割台尺寸;
    uint16_t宽度;
    uint16_t高度;
    uint16_t平面;
    uint16位深度;
    };
    结构InfoV1Header
    {
    uint32_t收割台尺寸;
    int32_t宽度;
    int32_t高度;
    uint16_t平面;
    uint16位深度;
    uint32_t压缩;
    uint32尺寸图像;
    int32_t x_分辨率;
    int32_t y__分辨率;
    uint32使用的颜色;
    uint32颜色很重要;
    };
    结构OS2Header:公共InfoV1Header
    {
    uint16分辨率单位;
    uint16保留;
    uint16\u t填充方向;
    uint16_t半色调算法;
    uint32半色调参数1;
    uint32半色调参数2;
    uint32_t颜色编码;
    uint32应用程序定义;
    };
    结构InfoV4Header:公共InfoV1Header
    {
    uint32红色遮罩;
    uint32绿色遮罩;
    uint32_t蓝色_面具;
    uint32阿尔法掩模;
    uint32_t cs_型;
    uint64_t红色_x;
    uint64红色;
    uint64_t red_z;
    uint64绿色;
    uint64绿色;
    uint64_t绿色_z;
    uint64_t蓝色_x;
    uint64_t蓝色_u u y;
    uint64_t蓝色_z;
    uint32_t伽马红;
    uint32_t伽马绿;
    uint32_t伽马_蓝;
    };
    结构InfoV5Header:公共InfoV4Header
    {
    uint32_t意图;
    uint32剖面图数据;
    uint32剖面尺寸;
    uint32保留;
    };
    类位图
    {
    公众:
    位图(路径中的std::字符串);
    ~Bitmap();
    无效保存(标准::字符串输出路径);
    私人:
    文件头*文件头;
    //信息标题选项
    核心头*核心头;
    os2头*os2_头;
    InfoV1Header*info\u v1\u header;
    Infov4头*Infov4头;
    InfoV5头*InfoV5头;
    void verify_file_header()常量;
    };
    #endif/*位图包含*/
    
    现在看起来似乎是最好的选择,但我对编写一系列方法的想法感到畏缩,这些方法从检查信息头中的nullptr开始。希望我错过了一些东西,因为我不太了解C++。
    (目前在c++14中工作,但如果有意义的话,不反对使用17。在Linux Zorin OS 15上,使用gcc 7.4和cmake 3.15.2。)

    一个随机无关点,V4头中的红色x到蓝色z字段是32位有符号整数,而不是上面的64位UINT(实际上,它们是FXPT2DOT30类型-具有2位整数部分的定点,30位十进制)

    处理此问题的典型方法是将整个BMP文件加载到一个大内存块中,然后重新解释数据。正如您所注意到的,V5派生自V4,V4派生自V1。考虑到决定文件中头类型的是头的大小,您可以执行穷人的动态转换。。。。

    
    结构信息头;
    结构OS2Header;
    结构信息头;
    结构InfoV5Header;
    结构InfoV1Header
    {
    uint32_t收割台尺寸;
    int32_t宽度;
    int32_t高度;
    uint16_t平面;
    uint16位深度;
    uint32_t压缩;
    uint32尺寸图像;
    int32_t x_分辨率;
    int32_t y__分辨率;
    uint32使用的颜色;
    uint32颜色很重要;
    模板
    内联常量T*as()常量;
    };
    结构OS2Header:公共InfoV1Header
    {
    uint16分辨率单位;
    uint16保留;
    uint16\u t填充方向;
    uint16_t半色调算法;
    uint32半色调参数1;
    uint32半色调参数2;
    uint32_t颜色编码;
    uint32应用程序定义;
    };
    结构InfoV4Header:公共InfoV1Header
    {
    uint32红色遮罩;
    uint32绿色遮罩;
    uint32_t蓝色_面具;
    uint32阿尔法掩模;
    uint32_t cs_型;
    int32_t red_x;
    int32_t red_y;
    int32_t red_z;
    int32_t绿色_x;
    国际绿色联盟;
    int32_t green_z;
    int32_t blue_x;
    int32_t blue_y;
    int32_t blue_z;
    uint32_t伽马红;
    uint32_t伽马绿;
    uint32_t伽马_蓝;
    };
    结构InfoV5Header:公共InfoV4Header
    {
    uint32_t意图;
    uint32剖面图数据;
    uint32剖面尺寸;
    uint32保留;
    };
    模板
    内联常量OS2Header*InfoV1Header::as()常量
    {
    返回标头_size==sizeof(OS2Header)?(const OS2Header*)此:0;
    }
    模板
    内联常量InfoV4Header*Info
    
    void doStuff(const InfoV1Header* v1)
    {
      // do stuff with the v1 fields
    
      if(const OS2Header* os2 = v1->as<OS2Header>())
      {
        // do stuff with os2 fields
      }
    
      if(const InfoV4Header* v4 = v1->as<InfoV4Header>())
      {
        // do stuff with v4 fields
      }
    
      if(const InfoV5Header* v5 = v1->as<InfoV5Header>())
      {
        // do stuff with v5 fields
      }
    }