将类添加到数组

时间:2013-12-20 14:27:37

标签: c++

我正在进行大学任务,使用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;
}

4 个答案:

答案 0 :(得分:3)

数组不是多态的:数组中存储的所有内容都必须是同一类型。你的Shape数组不起作用。 1

那么在使用数组时如何获得多态性呢?更改数组以将指针存储到Shape

 Shape *aShapes[5];

这很好地解决了问题:Shape*可以指向Shape or any of its descendants 2 ,并且所有Shape*本身都是相同的类型。

然后在主代码中,将对象的地址存储在数组中:

 aShapes[i] = &square;

您需要对现有代码进行一些其他更改才能使其正常工作:


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。这很糟糕。

然而,使用指针,您不会切片。

您的特定错误源于使用私有继承,该继承禁止转换为继承的类。使用公共继承。这只是掩盖了上述问题。