在C 中的数组中存储抽象基类的不同派生类的对象

Storing objects of different derived classes of an abstract base class in an array in C++

本文关键字:派生 对象 抽象 数组 存储 基类      更新时间:2023-10-16

我是一个完整的初学者,试图学习C 。因此,这个问题听起来很陈词滥调。请帮助我了解我出错的地方。

问题在下面描述。

目标:

  1. 将抽象类形状定义为接口。(使用纯虚拟功能)
  2. 覆盖派生类矩形,圆,三角形中的方法。
  3. 需要两个功能 - a。read() ->读取特定形状的输入参数(测量)。 b。区域() ->计算形状的总面积。
  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.hpp triangle.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.cpp triangle.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中,我指定了方法1 方法2 作为主函数中的注释行。

方法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上的其他建议后,可以实现类似的功能。但是现在我遇到了一个错误。

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)
       ^~~~~~~~~

我不明白如何纠正这一点。因此,我陷入了这个问题,无法解决该问题。请帮助我理解和纠正错误。

您只是忘记指定,您的类rect2d :: retectangle实现了您的抽象接口类别类别:: Shape。

您可以通过添加

来做到这一点

:公共将军:: Shape

rect2d ::矩形的声明。固定声明是:

namespace rect2D
{
 class Rectangle : public generalShape::Shape {
     private :
         double length;
         double breadth;
     public :
         void read();
         double area() ;
 };
}

还有一个提示:请在基类将军:: Shape中定义一个虚拟破坏者,如果您打算通过容纳基类指针的容器破坏对象。