【问题标题】:Storing objects of different derived classes of an abstract base class in an array in C++在C ++中将抽象基类的不同派生类的对象存储在数组中
【发布时间】:2019-07-31 19:06:29
【问题描述】:

我是一个尝试学习 C++ 的完整初学者。所以,这个问题可能听起来很陈词滥调`。请帮助我了解我哪里出错了。

问题描述如下。

目标:

  1. 定义一个抽象类Shape作为接口。 (使用纯虚函数)
  2. 覆盖派生类 Rectangle、Circle、Triangle 中的方法。
  3. 需要两个函数 - a. read() -> 读取特定形状的输入参数(测量值)。 湾。 area() -> 计算形状的总面积。
  4. 将不同派生类的对象(或指向对象的指针)存储在一个数组中。
  5. 计算每个数组成员的面积。
  6. 计算总面积。

代码片段:

shape.hpp - 基类头文件。

namespace generalShape
{
 class Shape { 
     public :          
         virtual void read() = 0;
         virtual double area() = 0 ;         
 };
}

rect.hpp - 派生类头文件。

namespace rect2D
{
 class Rectangle {
     private :
         double length;
         double breadth;

     public :
         void read();
         double area() ;           
 };
}

也为另外两个派生类编写了类似的头文件, 即circle.hpptriangle.hpp

rect.cpp - 派生类实现文件。

using namespace rect2D;

// Read data (use it in main.cpp)
void Rectangle::read(/* no args */)
{   
 std::cin >>  length;  
 std::cin >>  breadth;
}

// To calculate area of a rectangle object
double Rectangle::area(/* no args */)
{ 
 return length * breadth;   
}

还为另外两个派生类编写了类似的实现文件, 即circle.cpptriangle.cpp

main.cpp - 客户端文件。

using namespace generalShape;
using namespace rect2D;
// similarly use other namespaces as required

int main()
{
 int number_of_shapes; // take input from user about number of objects
 double total_area = 0;

 /* Method 1 */
 Shape **arr;
 arr = new Shape*[size];

 /* Method 2 */
 //vector<Shape *> arr;

 for (int i = 0; i < number_of_shapes; i++)
 {
     // some code to ask user about type of object

     if (choice == 1)//based on user input
     {
         arr[i] = new Rectangle();       // for method 1
         //arr.push_back(new Rectangle); // for method 2
     }

     // similar code for other derived class object types

     // Code to calculate total_area of all objects in array.
     arr[i]->read();
     total_area += arr[i]->area();
 }
 return 0;
}

我的问题是什么?

在 main.cpp 中,我已将 Method 1Method 2 指定为 main 函数中的注释行。

方法 1 尝试使用 基类指针数组来指向不同类的派生类对象(这是允许的,对吗?)。但它给出了一个错误。 error: cannot convert ‘rect2D::Rectangle*’ to ‘generalShape::Shape*’ in assignment和其他派生类对象的类似错误。

所以,我尝试通过类型转换来解决这个问题。

// Shape is the base class with virtual methods read() and area().
// Rectangle,Triangle,Circle are derived classes which override these methods.
// main.cpp uses these header files to read user input using read() for each 
// derived class and then calculate area using area(). The ultimate goal is to 
// calculate total area of all derived class objects stored in an array.

arr[i] = (Shape*)(new Rectangle()) ;

这样做,允许编译没有错误。但是当我尝试执行时,它会出现分段错误。我不确定为什么会这样。但我认为是因为我在基类头文件中定义了纯虚函数。即使是这样,我也不确定如何纠正它。

其次,在方法2中,我在查看了stackoverflow上的其他建议后,尝试使用vectors来实现类似的功能。但现在我遇到了一个错误。

error: no matching function for call to ‘std::vector<generalShape::Shape*>::push_back(rect2D::Rectangle*)’
             arr.push_back(new Rectangle);
                                        ^
In file included from /usr/include/c++/7/vector:64:0,
                 from src/main.cpp:2:
/usr/include/c++/7/bits/stl_vector.h:939:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = generalShape::Shape*;
_Alloc = std::allocator<generalShape::Shape*>; std::vector<_Tp, _Alloc>::value_type = generalShape::Shape*]
       push_back(const value_type& __x)
       ^~~~~~~~~
/usr/include/c++/7/bits/stl_vector.h:939:7: note:   no known conversion for argument 1 from ‘rect2D::Rectangle*’ to ‘generalShape::Shape* const&’
/usr/include/c++/7/bits/stl_vector.h:953:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = generalShape::Shape*; _Alloc = std::allocator<generalShape::Shape*>; std::vector<_Tp, _Alloc>::value_type = generalShape::Shape*]
       push_back(value_type&& __x)
       ^~~~~~~~~

我无法理解如何纠正这个问题。所以,我被这个问题困住了,无法解决。请帮助我理解并纠正错误。

【问题讨论】:

  • 欢迎来到 SO。请不要链接到我们必须去参考您的问题的外部地方。这是一个问答网站,每个问题都必须是独立的,并带有正确的minimal reproducible example。由于您是新手,我建议您使用tour,访问help center 并阅读How to Ask 适合这种格式的问题。
  • 好的。参观后,我将编辑我的问题以包含代码。感谢您指出这一点。
  • 如果你有两个类,B(作为基类)和C(作为从B继承的子类),那么指向C的指针不会需要使用B* 进行投射。事实上,任何类型的 C 风格转换都是一个危险信号,可能意味着你做错了什么。
  • @Someprogrammerdude 是的,我也这么认为。我只是想看看,当我这样做时程序是否编译。因为,如果确实如此,那就意味着,我肯定在某个地方犯了错误。而且,它确实编译了。所以,我确定我错了。

标签: c++ arrays inheritance polymorphism abstract-class


【解决方案1】:

您只是忘了说明,您的类 rect2D::Rectangle 实现了您的抽象接口类 generalShape::Shape。

你可以通过添加来做到这一点

: public generalShape::Shape

到 rect2D::Rectangle 的声明。 那么固定的声明是:

namespace rect2D
{
 class Rectangle : public generalShape::Shape {
     private :
         double length;
         double breadth;

     public :
         void read();
         double area() ;
 };
}

另一个提示:如果您打算通过保存基类指针的容器销毁您的对象,请在您的基类 generalShape::Shape 中定义一个虚拟析构函数。

【讨论】:

  • 非常感谢!!这确实是我监督的一个非常糟糕的案例。
猜你喜欢
  • 2018-09-17
  • 2013-08-30
  • 2012-02-05
  • 1970-01-01
  • 1970-01-01
  • 2015-03-23
  • 2013-03-27
相关资源
最近更新 更多