【问题标题】:C++: hide method from childrenC++:对孩子隐藏方法
【发布时间】:2017-11-01 12:50:39
【问题描述】:

我有一个名为transform 的类及其子类translationrotationscaling,它们应该对三角形应用变换。

每个子类都覆盖apply_transform() 方法:

class transform
{
protected:
    virtual triangle apply_transform(const triangle&) const = 0;
public:
    static triangle apply_transforms(const triangle&, const std::initializer_list<const transform*>&);
};

class scaling : public transform
{
...
public:
    triangle apply_transform(const triangle&) const override;
};

//same for rotation and translation

我还有一个叫做apply_transforms的函数,它应该可以被外界访问,我用它来应用多个转换。我将transform* 的列表传递给它以启用多态性。

我唯一的问题是,现在子类也知道这种方法。这让我很困扰,因为子类不应该能够应用所有其他转换。

有没有一个优雅的解决方案?

【问题讨论】:

  • 好吧,您要么拥有对外界可见的函数(包括派生类),要么将其隐藏给所有人。
  • apply_transforms 可以在三角形类上是公共静态的吗?
  • 我建议您不要再为此烦恼了。是不是我这个跟几何无关的字符串类也可以访问这个函数?

标签: c++ oop inheritance polymorphism information-hiding


【解决方案1】:

使apply_transforms 成为一个非成员函数,它不包含在实现transform 的类所需的头文件中。

【讨论】:

    【解决方案2】:

    我建议稍微改变一下你对变换的看法。

    1. 使transform 成为一个类,这样它就不需要从它派生其他类。转换一个点所需的所有数据都可以保存在这个类中。

    2. 添加构造缩放变换、平移变换和旋转变换的函数。

    3. 添加函数以乘以变换,以及乘以变换和点。这些可以作为转换其他形状的构建块。

    4. 根据需要添加转换其他形状的函数。


    以骨骼形式,

    class transform { ... };
    class position { ... };
    
    // tag structs
    struct rotation_about_x {};
    struct rotation_about_y {};
    struct rotation_about_z {};
    
    // Functions to construct transforms
    transform construct_scale_transform(double scale_factor) { ... };
    transform construct_translation_transform(position pos) { ... };
    transform construct_rotation_transform(double angle, rotation_about_x tag) { ... };
    transform construct_rotation_transform(double angle, rotation_about_y tag) { ... };
    transform construct_rotation_transform(double angle, rotation_about_z tag) { ... };
    
    // Function to transform a point.
    position operator*(transform const& t, position const& p) { ... }
    
    // Function to multiply transforms.
    transform operator*(transform const& t1, transform const& t2) { ... }
    
    
    // Functions to apply transforms to other objects.
    triangle operator*(transform const& tr, triangle const& t) { ... }
    ...
    

    用法:

    transform t1 = construct_rotation_transform(10, rotation_about_x{});
    transform t2 = construct_translation_transform({20, 10, 0});
    
    position p1{100, 200, 30};
    position p2 = t1*t2*p1;
    
    triangle tr1{ ... }
    triangle tr2 = t1*t2*tr1;
    

    如果您要多次使用相同的组合变换,请先计算组合变换并将其用于所有变换。

    transform t1 = construct_rotation_transform(10, rotation_about_x{});
    transform t2 = construct_rotation_transform(5, rotation_about_y{});
    transform t3 = construct_translation_transform({20, 10, 0});
    tranform tc = t1 * t2 * t3;
    
    position p1{100, 200, 30};
    position p2 = tc*p1;
    
    triangle tr1{ ... }
    triangle tr2 = tc*tr1;
    

    【讨论】:

    • 但请注意,使用 * 的“自然”语法在 C++ 中始终是从左到右关联的,这可能效率低下:en.wikipedia.org/wiki/Matrix_chain_multiplication
    • @BenVoigt,说得好。幸运的是,您可以计算组合变换并根据需要多次使用它。
    【解决方案3】:

    事实上,由于您的 apply_transforms(...) 方法是公开的,因此所有潜在的调用者都可以使用它。考虑到这一点,您不能也不应该阻止子类看到这些方法。

    如果您知道您的方法将从特定的类中调用,您可以将您的方法设为私有并将这些调用类声明为好友。

    否则,将方法封装在不同的类中,以防止transform的子类包含它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-06
      • 1970-01-01
      • 2017-10-11
      • 2014-11-21
      • 2021-06-10
      • 1970-01-01
      • 2010-11-13
      • 2011-07-20
      相关资源
      最近更新 更多