【问题标题】:How do I add child class objects to a vector of their parent class (C++)?如何将子类对象添加到其父类 (C++) 的向量中?
【发布时间】:2014-09-09 06:59:04
【问题描述】:

我有各种形状类,从矩形、圆形、正方形、五边形等,Shape 类的所有子类,并且所有这些类都有一个 getArea() 方法来返回它们的面积。我正在尝试制作一个 Shape 向量,它可以添加所有这些形状的面积,这样我就可以使用一个函数来计算总面积。这是我遇到问题的代码部分。我还没有完成 getTotalArea 方法的编写,但这很容易。我只需要知道如何命名该方法(getTotalArea 方法)以及使用什么引用或指针。另外,我可以编译 main 方法的底部的唯一方法是在向量​​中使用 Shape 的指针,并在将子对象添加到向量时引用它们:

vector<Shape*> shapes;
shapes.push_back(&circle);

有什么想法吗?非常感谢您的帮助。

#include <iostream>
#include "shape.h"
#include "point.h"
#include <vector>
using namespace std;
double getTotalArea(vector<Shape> sh)
{
  return 0;
}
int main(int argc, char** argv)
{
  vector<Point> my_points;
  my_points.push_back(Point(2, 3));
  my_points.push_back(Point(1, 1));
  my_points.push_back(Point(3, 1));
  cout << "Points for a triangle:\n\n";
  Triangle triangle(my_points);
  cout << triangle << "area = " << triangle.getArea();
  my_points.clear();

  my_points.push_back(Point(2, 7));
  my_points.push_back(Point(9, 7));
  my_points.push_back(Point(2, 3));
  my_points.push_back(Point(9, 3));
  cout << "\n\nPoints for a rectangle:\n\n";
  Rectangle rectangle(my_points);
  cout << rectangle << "area = " << rectangle.getArea();
  my_points.clear();

  my_points.push_back(Point(0, 5));
  my_points.push_back(Point(5, 5));
  my_points.push_back(Point(0, 0));
  my_points.push_back(Point(5, 0));
  cout << "\n\nPoints for a square:\n\n";
  Square square(my_points);
  cout << square << "area = " << square.getArea();
  my_points.clear();

  my_points.push_back(Point(0, 5));
  my_points.push_back(Point(6, 6));
  my_points.push_back(Point(10, 5));
  my_points.push_back(Point(8, 3));
  my_points.push_back(Point(1, 2));
  cout << "\n\nPoints for a pentagon:\n\n";
  Pentagon pentagon(my_points);
  cout << pentagon << "area = " << pentagon.getArea();
  my_points.clear();

  my_points.push_back(Point(3, 5));
  cout << "\n\nLength of semi-major axis and length of semi-minor axis for an oval (put in a Point object)):\n\n";
  Oval oval(my_points);
  cout << oval << "area = " << oval.getArea();
  my_points.clear();

  cout << "\n\nRadius of a circle (first parameter of a Point object - second is ignored):\n\n";
  my_points.push_back(Point(12, 0));  //the second argument here can also be NULL
  Circle circle(my_points);
  cout << circle << "area = " << circle.getArea();
  my_points.clear();

  vector<Shape*> shapes;
  shapes.push_back(&circle);
  shapes.push_back(&rectangle);
  shapes.push_back(&square);
  shapes.push_back(&pentagon);
  shapes.push_back(&oval);
  shapes.push_back(&circle);
  double totalArea = getTotalArea(shapes);

  return 0;
}

我解决了我遇到的问题,感谢你们中的一些人为我指明了正确的方向。这就是我得到的,它可以正常工作:

  //a function outside the main method
  void displayTotalArea(vector<Shape*>& sh)
  {
     double total = 0;

     for (int x = 0; x < sh.size(); x++)
     {
       total += sh[x]->getArea();
     }
     cout << "\n\nTotal area of all shapes = " << total;
  }

  //in the main method
  vector<Shape*> shapes;
  shapes.push_back(&pentagon);
  shapes.push_back(&triangle);
  shapes.push_back(&rectangle);
  shapes.push_back(&square);
  shapes.push_back(&pentagon);
  shapes.push_back(&oval);
  shapes.push_back(&circle);
  displayTotalArea(shapes);

【问题讨论】:

  • 你有一个vector&lt;Shape*&gt; - 换句话说,一个基类指针的向量。因此,您必须为每个派生类 push_back Shape*dynamic_cast&lt;Shape*&gt; 您的派生引用,然后再将它们推送到向量上。 getArea() 通常是基类中的 virtual,这意味着您可以通过基类指针访问该方法的派生类覆盖。
  • @HvS dynamic_cast 在这里太过分了:upcast 是静态的和隐式的。
  • @Quentin,是的,你是对的,我只是喜欢 dynamic_cast :)

标签: c++ pointers inheritance reference parent-child


【解决方案1】:

如果我明白你在做什么,这会很好:

double getTotalArea(const vector<Shape*>& sh)
{
    double tot = 0;

    for (Shape* s : sh)
        tot += s->getArea();
        
    return tot;
}

将子元素添加到容器中(然后使用vector&lt;Shape&gt; 而不是vector&lt;Shape*&gt;,这样会更好,因为当向量超出范围时,使用非指针版本会释放形状):

Triangle t;
Oval v;
std::vector<Shape> container;
container.push_back(t);
container.push_back(v);

编译成功:

#include <iostream>
#include <vector>

class A {};
class B : public A {};
class C : public A {};

int main()
{
    std::vector<A> vec;
    vec.push_back(B());
    vec.push_back(C());
    
    B instance;
    vec.push_back(instance);
    
    return 0;
}

【讨论】:

  • 你在这里切片对象。 B 和 C 的派生部分在 push_back 期间丢失。
  • @Quentin:哇!你说得对……是 std::vector<:shared_ptr>> 那么要走的路(避免裸ptr,让vector管理资源)?
  • 如果vectors要拥有资源,你正在寻找std::vector&lt;std::unique_ptr&lt;Shape&gt;&gt; :)
猜你喜欢
  • 2020-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-22
  • 1970-01-01
  • 1970-01-01
  • 2018-11-24
  • 2021-05-31
相关资源
最近更新 更多