我正在进行大学任务,使用OOP查找不同形状的数组。 我创建了所有的形状类,因此它们来自我的主要Shape类。 Shape类正如接口一样使用,因此从shape类派生的所有形状类都必须具有计算区域函数等。 我想创建一个不同形状的数组。我已经声明了一个形状类型的数组,它是父类,我想将每个不同形状,圆形,正方形,矩形和三角形的新实例添加到数组列表中,以便存储有关每个形状的所有信息。一个阵列。我有以下代码,但我在行 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;
}
答案 0 :(得分:3)
数组不是多态的:数组中存储的所有内容都必须是同一类型。你的Shape
数组不起作用。 1
那么在使用数组时如何获得多态性呢?更改数组以将指针存储到Shape
:
Shape *aShapes[5];
这很好地解决了问题:Shape*
可以指向Shape
or any of its descendants, 2 ,并且所有Shape*
本身都是相同的类型。
然后在主代码中,将对象的地址存储在数组中:
aShapes[i] = □
您需要对现有代码进行一些其他更改才能使其正常工作:
Shape
virtual。Square
中的方法覆盖Shape
public 定义的界面。 1 如果您做设法将Shape
的后代复制到数组中,那么您最终会slicing the object。
2 技术性:如果您提供Shape
pure virtual方法,则无法创建纯Shape
的实例。在这种情况下,Shape*
无法指向Shape
的实例,因为您无法创建一个! Shape*
只会指向其后代中的一个实现所有虚拟方法。
答案 1 :(得分:1)
您收到该特定错误的原因是因为当您真正希望使用private
继承时,您正在使用public
继承。
class Square : public Shape {
^^^^^^
另一个问题是多态性仅适用于指针或引用。您无法将Square
放入Shapes
数组中。它将简单地切出Shape
的{{1}}部分并将其放入数组中。 Square
只不过是Shape aShapes[5];
的数组 - 没有Shapes
,没有Squares
,只有Triangles
。你需要的是:
Shapes
然后,您可以将此数组中的指针设置为指向派生自Shape* aShapes[5];
的类型的对象。
您还需要在派生类Shape
中创建要覆盖的函数。当编译器看到像virtual
这样的东西,然后看到aShapes[0]->fnCalculateArea()
是一个虚函数时,它只会查找fnCalculateArea
指向的对象的动态类型 - 然后它会看到它是aShapes[0]
并致电Square
。
答案 2 :(得分:1)
1)你私下继承Shape,这通常是一种不受欢迎的组合形式。为了您的目的,您应该公开继承Shape。
class Square : public Shape
2)Shape的成员函数都没有被声明为虚拟,因此派生类都不会覆盖它们。您也没有虚拟析构函数。如果你希望在指向Square的Shape指针上调用Square的CalculateArea函数时,你必须在Shape中声明为virtual,并在Square中覆盖它:
形状:
virtual float fnCalculateArea();
广场:
void float fnCalculateArea() override;
3)如果Shape应该仅作为一个抽象接口,而不是自己实例化,那么你应该通过使其中一个函数纯虚拟(至少是析构函数,如果没有其他函数)来实现它。
virtual ~Shape() = 0 {}
4)如果要将不同的派生类型存储在单个容器中,则必须通过引用存储它们,IE通过指向其基类的指针存储它们。
Shape* aShapes[5];
5)我还注意到你使用n
为许多变量名加前缀,即使它们是浮点数。匈牙利表示法通常使用n
来表示整数,f
表示浮点数。
答案 3 :(得分:0)
值的数组不具有多态性。您将不得不使用指向Shape的指针数组,因为对指针的访问和赋值确实具有多态性。
你所拥有的是对象切片,你正在切断Derived类块,以便你的对象适合Base。这很糟糕。
然而,使用指针,您不会切片。
您的特定错误源于使用私有继承,该继承禁止转换为继承的类。使用公共继承。这只是掩盖了上述问题。