向数组中添加类
Adding Classes to an Array
我正在做一项关于使用OOP查找不同形状数组的大学作业。我已经创建了我所有的形状类,所以它们派生自我的主形状类。形状类被用作接口,因此从形状类派生的所有形状类都必须具有计算面积函数等。我想创建一个不同形状的数组。我已经声明了一个具有形状类型的数组,它是父类,我想将每个不同形状、圆形、方形、矩形和三角形的新实例添加到数组列表中,以便将每个形状的所有信息存储在一个数组中。我有下面的代码,但我在aShapes[I]=square这行有一个错误说形状是正方形难以接近的基础。
如果有人能帮忙,那就太好了。
提前感谢。
这是我的代码
#include <cstdlib>
#include <iostream>
#define M_PI 3.14159265358979323846
using namespace std;
class Shape{
public:
string sName;
float nArea;
void fnAddData();
float fnCalculateArea();
};
class Square : private Shape {
private:
float nSide;
void fnAddData()
{
cout << "Please enter the length of a side: ";
cin >> nSide;
}
float fnCalculateArea(float side)
{
return (side * side);
}
public:
Square()
{
sName = "Square";
fnAddData();
nArea = fnCalculateArea(nSide);
}
};
Shape aShapes[5];
/*
*
*/
int main(int argc, char** argv)
{
int decision;
Square square;
for (int i = 0; i < 5; i++)
{
cout << "Shape number";
cin >> decision;
switch (decision)
{
case 1:
aShapes[i] = square;
}
}
return 0;
}
数组不是多态的:存储在数组中的所有内容都必须是相同的类型。你的Shape
数组不起作用1
那么,在使用数组时,如何获得多态性呢?更改数组以存储指向Shape
:的指针
Shape *aShapes[5];
这很好地解决了这个问题:Shape*
可以指向Shape
或其任何子代2,并且所有Shape*
本身都是相同的类型。
然后在主代码中,存储数组中对象的地址:
aShapes[i] = □
您需要对现有代码进行一些其他更改才能使其工作:
- 使用公共继承,而不是私有传承
- 使
Shape
中的方法虚拟化 - 使
Square
中重写Shape
定义的接口的方法为public - 添加一个虚拟析构函数
1如果成功地将Shape
的后代复制到数组中,则最终会对对象进行切片
2技术性:如果给Shape
提供纯虚拟方法,则无法创建纯Shape
的实例。在这种情况下,Shape*
不能指向Shape
的实例,因为您无法创建一个实例!Shape*
将仅指向其实现所有虚拟方法的子代之一
出现该错误的原因是,您使用的是private
继承,而实际上您确实希望使用public
继承。
class Square : public Shape {
^^^^^^
另一个问题是多态性只适用于指针或引用。不能将Square
放入Shapes
的数组中。它将简单地切出Square
的Shape
部分,并将其放入阵列中。Shape aShapes[5];
只不过是Shapes
的数组——没有Squares
,没有Triangles
,只有Shapes
。你需要的是这样的东西:
Shape* aShapes[5];
然后,您可以将此数组中的指针设置为指向从Shape
派生的类型的对象。
您还需要制作要在派生类virtual
中重写的函数。当编译器看到类似aShapes[0]->fnCalculateArea()
的东西,然后看到fnCalculateArea
是一个虚拟函数时,它只会查找aShapes[0]
指向的对象的动态类型——然后它会看到它是一个Square
并调用Square::fnCalculateArea
。
1)您私下继承了Shape,这通常是一种不受欢迎的合成形式。出于您的目的,您应该公开继承Shape。
class Square : public Shape
2) Shape的任何成员函数都没有声明为虚拟的,因此它们都不会被派生类覆盖。您也没有虚拟析构函数。如果要在指向正方形的Shape指针上调用Square的CalculateArea函数,则必须在Shape中声明为虚拟,并在Square:中覆盖它
形状:
virtual float fnCalculateArea();
方形:
void float fnCalculateArea() override;
3) 如果Shape应该只作为一个抽象接口,而不是实例化它自己,那么你应该通过使它的一个函数纯虚拟(如果没有其他函数的话,至少是析构函数)来实现它。
virtual ~Shape() = 0 {}
4) 如果你想将不同的派生类型存储在一个容器中,那么你必须通过引用来存储它们,IE通过指向它们基类的指针来存储它们。
Shape* aShapes[5];
5) 我还注意到,您在许多变量名前面加了n
,尽管它们是浮点值。匈牙利表示法通常使用n
表示int,使用f
表示float。
值数组的行为不具有多态性。您将不得不使用一个指向Shape的指针数组,因为对指针的访问和赋值确实具有多态性。
这里的方法是对象切片,即剪切Derived类块,使对象适合Base。这太糟糕了。
然而,有了指针,就不会得到切片。
您的特定错误源于使用私有继承,它禁止转换到继承的类。使用公共继承。这只是掩盖了上述问题。
- 如何将元素添加到数组的线程安全函数?
- C++ 动态数组每次添加时将大小增加 1 - 错误
- 运算符重载 (+),用于添加两个具有 C++ 的数组
- 添加到数组指针
- 将随机生成的数字添加到数组 + 对这些数组求平均值
- 将数组的元素添加到链表中
- 如何在C++中将元素添加到非固定大小的数组中?
- 将在堆栈上声明的元素添加到静态数组
- const_cast静态数组以添加恒常性
- 在 char* 数组中添加两个索引
- c++ 如何在数组的开头添加值并为其编制索引?
- 检查数组中是否有字符串中的值,如果没有,则添加它
- 添加数组特定列的元素
- 添加数组元素:需要左键作为赋值的左操作数
- 添加数组所有元素的 SSE 指令
- 如何添加数组的偶数和奇数之和
- 向std::multimap添加数组值
- 用内部类函数递归地添加数组数
- 使用自增操作符添加数组元素
- 创建一个模板函数,如果数据类型不同,则添加数组的元素