【问题标题】:Pointers to elements of a C++ class指向 C++ 类元素的指针
【发布时间】:2015-12-30 08:10:26
【问题描述】:

我有一个 C++c_image,它包含一个指向类 c_pixel 元素的指针向量:

class c_image {

    public:
        vector<shared_ptr<c_pixel>> pixel;
    ...
};

c_pixel 元素包含一个 double 类型的元素 Z

class c_pixel {

    public:
        double Z;
    ...
};

但是,它们使用类 c_pixel_pv 进行了扩展,其中包含 pv,一个由三个 double 类型元素组成的数组:

class c_pixel_pv : public c_pixel {

    public:
        double pv[3];
    ...
};

c_image也有一个函数filter

vector<double> c_image::filter(???) {
        ...
    };

它将把指向元素Zpv[0]pv[1]pv的指针作为输入[2]

但我不知道如何指向这些元素。例如,我什至不知道是否可以仅指向 pv[0] 元素。我不知道如何从这个问题开始。有人可以帮帮我吗?

【问题讨论】:

  • 如果它是 z 或 pv[0] 或...,函数的行为会有所不同吗?
  • 不就是double*吗?毕竟Zpv[..]都是双打!
  • 你不能有一个“成员指针”可以指向“可能在成员内部,也可能不在”(注意pv[0]不是c_pixel_pv的成员,只有pv是)。不过,您的问题引发了许多其他问题,例如:为什么要共享像素?共享这些像素的图像是什么?图像是否可以包含c_pixelc_pixel_pv 的混合体?
  • @HumamHelfawi 不,完全一样
  • @molbdnilo 这是一个复杂的类结构,但如果你了解整个问题,这是必要的。

标签: c++ class pointers


【解决方案1】:

您可以(并且可能应该)使用多态性,并在c_pixel 类中拥有一个在c_pixel_pv 类中被覆盖的虚成员函数。此成员函数使用正确的成员变量执行所需的任何操作,并从c_image::filter 调用。

【讨论】:

  • 函数 c_image::filter 可以是例如中值平滑滤波器,它针对图像的每个像素计算其周围像素的中值。在这种情况下,单个元素 c_pixel 没有平滑它所需的所有信息。这就是为什么我认为过滤器不能作为 c_pixel 上的函数运行。
  • @Medicalphysicist 但这是您应该做出的选择,我的意思是如果中值平滑不适用于 c_pixel,则不要在结果集中包含该像素。
  • @Medicalphysicist 您可以使用例如dynamic_cast 检查指针是指向基类还是子类的指针,但这会导致 code smell 和代码变得难以阅读、理解和维护。也许您应该有两个“过滤器”功能,一种用于每种类型的像素。这可能是一种边缘代码气味,但至少它更好。我认为你真正需要做的是重新思考你的设计,你真的需要不同的像素类型吗?一张图片可以同时拥有两种类型吗?
【解决方案2】:

OOP 概念 - 多态 现在会派上用场。 c_pixel 类中的虚拟成员函数(虚拟成员是可以在派生类中重新定义的成员函数,同时通过引用保留其调用属性),在派生类c_pixel_pv 中被覆盖,可以执行操作你需要正确的变量。

您需要从vector&lt;double&gt; c_image::filter() 调用此成员函数。

【讨论】:

    【解决方案3】:

    你可以使用函数而不是指针:

    using Selector = std::function<double(const c_pixel&)>;
    
    vector<double> c_image::filter(Selector select) {
        // Trivial example that just copies
        vector<double> result;
        result.reserve(pixel.size());
        for (auto pix: pixel)
        {
            result.push_back(select(*pix)); 
        }
        return result;
    };
    
    double z(const c_pixel& p)
    {
        return p.Z;
    }
    
    c_image image;
    // ...
    vector<double> = image.filter(z);
    

    但是您需要一些方法来区分不同类型的像素,例如标记字节或虚拟函数(因此它们会占用更多空间并且您已经有很多开销)。

    如果您不需要在图像中混合像素类型,您可以使用模板类,以像素类型为模板。
    然后你可以摆脱运行时像素歧视。
    (说实话,很难想象像filter 这样的函数会如何处理没有它应该使用的元素的类型的像素。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-04
      • 2021-02-02
      • 2011-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多