根据子构造器参数使用不同的参数调用父构造器

时间:2018-10-28 12:20:22

标签: c++ oop inheritance

是否有一种方法可以根据子构造函数具有的参数值使用不同的参数调用父构造函数?

我有以下父类:

class Rectangle
{
public:
    Rectangle(std::string name, glm::vec3 top_left_corner, float height, float width, glm::vec3 color, bool fill);
    ~Rectangle();
    //...
}

子类:

class Wall :
    public Rectangle
{
public:
    Wall(std::string name, Position position, float scene_height, float scene_width, float thickness, glm::vec3 color);
    ~Wall();
    //...
}

Positionenum的地方,应该规定应使用哪些父构造函数来调用参数:

enum Position { UP, DOWN, LEFT, RIGHT };

因此,基本上,我想在子构造函数中添加以下内容:

Wall::Wall(std::string name, Position position, float window_height, float window_width, float thickness, glm::vec3 color) {
    switch(position) {
    case UP:
        Rectangle(name, glm::vec3(0, window_height, 0), thickness, window_height, color, true);
        break;
    case DOWN:
        Rectangle(name, glm::vec3(0, thickness, 0), thickness, window_width, color, true);
        break;
    case LEFT:
        Rectangle(name, glm::vec3(0, window_height, 0), window_height, thickness, color, true);
        break;
    case RIGHT:
        Rectangle(name, glm::vec3(0, window_width - thickness, window_height), window_height, thickness, color, true);
        break;
    }
}

但是您知道,我必须先调用父构造函数,例如:

Wall::Wall(std::string name, Position position, float window_height, float window_width, float thickness, glm::vec3 color)
    : Rectangle(name, glm::vec3(0, window_width - thickness, window_height), window_height, thickness, color, true) {}

那并没有给我太多余地。好的,面向对象的方法是什么?

4 个答案:

答案 0 :(得分:5)

创建工厂方法:

Rectangle MakeRectangle(const std::string& name,
                        const Position& position,
                        float window_height, float window_width,
                        float thickness,
                        const glm::vec3& color)
{
    switch(position) {
    case UP:
        return Rectangle(name,
                         glm::vec3(0, window_height, 0),
                         thickness,
                         window_height,
                         color,
                         true);
    case DOWN:
        return Rectangle(name,
                         glm::vec3(0, thickness, 0),
                         thickness,
                         window_width,
                         color,
                         true);
    case LEFT:
        return Rectangle(name,
                         glm::vec3(0, window_height, 0),
                         window_height,
                         thickness,
                         color,
                         true);
    case RIGHT:
        return Rectangle(name,
                         glm::vec3(0, window_width - thickness,  window_height),
                         window_height,
                         thickness,
                         color,
                         true);
    }
    throw std::runtime_error("Invalid position");
}

然后

Wall::Wall(std::string name,
           Position position,
           float window_height, float window_width,
           float thickness,
           glm::vec3 color)
: Rectangle(MakeRectangle(name, position, window_height, window_width, thickness, color)){
// ...
}

答案 1 :(得分:1)

如果我没看错,在所有情况下,您都调用父类的同一构造器,它们的参数是不同的。在此设置中,您可以借助函数“注入”任意代码。例如

class Wall {
  private:
  static glm::vec3 top_left_corner(Position position, float window_height, float window_width, float thickness) {
    switch (position) {
      case UP: return glm::vec3(0, window_height, 0);
      case DOWN: return glm::vec3(0, thickness, 0);
      case LEFT: return glm::vec3(0, window_height, 0);
      case RIGHT: return glm::vec3(0, window_width - thickness, window_height);
    }  
  }

  // similary for other arguments

然后您可以像这样调用构造函数:

Wall::Wall(std::string name, Position position, float window_height, float window_width, float thickness, glm::vec3 color)
: Rectangle(name,
    top_left_corner(position, window_height, window_width, thikness),
    ....... /* other arguments */
) {}

答案 2 :(得分:0)

我不知道什么是好的OOP方法,但是如果您想要的话,我确实知道如何在.obj的编译时执行此操作。

machine code

编辑:

实际上,为方便起见,您可以使用C++来代替类template <class T, T val> struct constant { #if __cplusplus >= 201703L constexpr const static inline T value = val; #else constexpr const static T value = val; #endif }; class Wall: public Rectangular { Wall(..., constant<Position, Position::UP>, ...): Rectangular(...) {} // Providing other overload to initialize your base code differently };

答案 3 :(得分:-1)

在构造函数中,您正在从父构造函数中的其他参数获取父类top_left_corner中的重复数据。

您可以使用top_left_corner更改enum,然后在构造函数中进行计算。

如果您不能更改父级构造函数,我认为您可以在父级初始化中使用lambda并使用与您编写的相同的开关大小写