编写此代码的更有效方法是什么?

What's a more efficient way to write this code?

本文关键字:有效 方法 是什么 代码      更新时间:2023-10-16

我是一个c++新手,我正在尝试学习继承。我写了一个程序,它只是简单地打印出不同形状的周长,即一个正方形和一个三角形。不幸的是,我这样做的方式导致了一些重复的代码。我的意思是:

#include <iostream>
class Shape {
public:
  int sides;
  int sideLength;
};
class Square : public Shape {
public:
  int sides = 4;
  int sideLength = 6;
  void calculatePerimeter() {
    int perimeter = sideLength * sides;
    std::cout << "perimeter length: " << perimeter << std::endl;
  }
};
class Triangle : public Shape {
public:
  int sides = 3;
  int sideLength = 4;
  void calculatePerimeter() {
    int perimeter = sideLength * sides;
    std::cout << "perimeter length: " << perimeter << std::endl;
  }
};
int main() {
  Square s;
  std::cout << "number of sides a square has: " << s.sides << std::endl;
  Triangle t;
  std::cout << "number of sides a triangle has: " << t.sides << std::endl;
  s.calculatePerimeter();
  t.calculatePerimeter();
}

可以看到,calculatePerimeter函数在Square和Triangle类中被使用。将其放入Shape类中并调用它,结果输出为0。我怎样才能使这更有效,所以我不需要复制/粘贴它为每一个形状类我做?

当您使用继承时,您在基类中考虑公共行为和状态,并使派生类用其特定的功能扩展此状态和行为。

  1. 从Shape中删除sides和sidelth成员。相反,在类Shape中提供返回这些值的虚函数,并让派生类覆盖它们。

  2. 移动方法计算圆周到类Shape,并使用getSides()和getSideLength()实现它

    #include <iostream>
    class Shape {
    public:
      virtual int getSides() = 0;
      virtual int getSideLength() = 0;
      void calculatePerimeter() {
        int perimeter = getSideLength() * getSides();
        std::cout << "perimeter length: " << perimeter << std::endl;
      }
    };
    class Square : public Shape {
    public:
      virtual int getSides() {
        return 4;
      }
      virtual int getSideLength() {
        return 6;
      }
    };
    class Triangle : public Shape {
    public:
      virtual int getSides() {
        return 3;
      }
      virtual int getSideLength() {
        return 4;
      }
    };
    

这就是所谓的模板方法设计模式(不要与c++的模板函数概念混淆,这是一个完全不相关的概念,特定于这种语言)。

您需要Shape的构造函数,并从派生构造函数传递变量。然后可以将calculatePerimiter移到父类中。

class Shape {
public:
  Shape(int n_sides, int side_length) : sides(n_sides), sideLength(side_length) {}
  void calculatePerimeter() {
    int perimeter = sideLength * sides;
    std::cout << "perimeter length: " << perimeter << std::endl;
  }
  int sides;
  int sideLength;
};
class Square : public Shape {
public:
  Square() : Shape(4,6) {}     
};
class Triangle : public Shape {
public:
  Triangle() : Shape(3, 4) {}
};

可以访问直接基类成员,也可以初始化它们。

class Shape {
public:
  int sides;
  int sideLength;
  Shape(int m,int n)
  {
      sides =m;
     sideLength = n;
  }
};
class Square : public Shape {
public:
  Square(int j,int k);
  int calculatePerimeter() {
    int perimeter = sides * sideLength ;
    std::cout << "perimeter length: " << perimeter << std::endl;
    return perimeter;
  }
};
Square::Square(int j,int k):Shape(j,k)
{

}

这将是我对支持c++ 11的编译器的方法…

#include <iostream>
#include <string>
#include <vector>
using namespace std;
template<class Seq>
void purge(Seq& s) {
    for (auto x: s) {
        delete x;
        x = nullptr;
    }
}
class Shape {
public: 
    virtual void calculatePerimeter() = 0; // to avoid object slicing
    virtual ~Shape() {};
};
class Square : public Shape {
    int m_sides{0};
    int m_sideLength{0};
public: 
    Square() = delete; // suppress default constructor
    Square(int sides, int sideLength): m_sides(sides), m_sideLength(sideLength) {}
    ~Square() {}
    void calculatePerimeter() {
        int perimeter = m_sideLength * m_sides;
        cout << "Square perimeter length: " << perimeter << endl;
    }
};
class Triangle : public Shape {
    int m_sides{0};
    int m_sideLength{0};
public: 
    Triangle() = delete; // suppress default constructor
    Triangle(int sides, int sideLength): m_sides(sides), m_sideLength(sideLength) {}
    ~Triangle() {}
    void calculatePerimeter() {
        int perimeter = m_sideLength * m_sides;
        cout << "Triangle perimeter length: " << perimeter << endl;
    }
};
int main() {
    vector<Shape*> vec;
    vec.push_back(new Square(4, 7));
    vec.push_back(new Triangle(3, 13));
    for (auto x: vec) {
        x->calculatePerimeter();
    }
    // clean up
    purge(vec);
    system("pause");
    return 0;
}

代码:

int sides = 3; int sideLength = 4;

正在用局部作用域视图创建新的变量。在不运行代码的情况下,我想如果你只是去掉两行前面的'int'应该可以解决你的问题。

编辑:把它们放到一个构造函数中。

编辑:Ok,组合代码…

    class Triangle : public Shape {
public:
  Triangle ()
  {
    sides = 3;
    sideLength = 4;
  }
  void calculatePerimeter() {
    int perimeter = sideLength * sides;
    std::cout << "perimeter length: " << perimeter << std::endl;
  }
};

取决于你想要理解的是什么,其他答案是更好的解决问题的方法。这很简单,只需将参数放入calalateperimeter()方法中,但这当然不能测试您对作用域中变量的理解,这似乎是您的绊脚石。

模板方式:

template <std::size_t SideCount, typename T>
class EquilateralPolygon
{
public:
    explicit EquilateralPolygon(T sideLength) : sideLength(sideLength) {}
    std::size_t GetSideCount() const { return SideCount; }
    T GetSideLength() const { return sideLength; }
    T calculatePerimeter() const { return SideCount * sideLength; }
private:
    T sideLength;
};
template <std::size_t SideCount, typename T>
void displayPerimeter(const EquilateralPolygon<SideCount, T>& p) {
    std::cout << "perimeter length: " << p.calculatePerimeter() << std::endl;
}
using EquilateralTriangle = EquilateralPolygon<3, std::size_t>;
using Square = EquilateralPolygon<4, std::size_t>;

和用法:

int main() {
    Square s(5);
    std::cout << "number of sides a square has: " << s.GetSideCount() << std::endl;
    EquilateralTrianglet(5);
    std::cout << "number of sides a triangle has: " << t.GetSideCount() << std::endl;
    displayPerimeter(s);
    displayPerimeter(t);
}

现场演示

这应该可以回答你的问题。此外,我建议将sidessideLength的值作为参数传递给函数调用,以启用通用用法。

#include <iostream>
class Shape {
    protected void calculatePerimeter(int sides, int sideLength) {
    int perimeter = sideLength * sides;
    std::cout << "perimeter length: " << perimeter << std::endl;
  }
};
class Square : public Shape {
  int sides = 4;
  int sideLength = 6;
  public void calculatePerimeter()
  {
      Shape::calculatePerimeter(sides, sideLength);
  }
};
class Triangle : public Shape {
  int sides = 3;
  int sideLength = 4;
  public void calculatePerimeter()
  {
      Shape::calculatePerimeter(sides, sideLength);
  }
};
int main() {
  Square s;
  std::cout << "number of sides a square has: " << s.sides << std::endl;
  Triangle t;
  std::cout << "number of sides a triangle has: " << t.sides << std::endl;
  s.calculatePerimeter();
  t.calculatePerimeter();
}