2017-06-03 2 views
2

Hey Leute hier ist ein Code, den ich laufen werde, Problem ist, dass es nicht so funktioniert, wie ich es vorhabe. Ich kann nicht herausfinden, was daran falsch ist. Ich bin C++ Noob bitte helfen.Wie können virtuelle Funktionen einer Superklasse für Enkelkinder in C++ außer Kraft gesetzt werden?

#include <iostream> 
#include <cmath> 
#include <stdexcept> 
using namespace std; 

/** 
* Super class 
*/ 
class Shape 
{ 
protected: 
    int _dimensions; 
public: 
    Shape() : _dimensions{0} 
    {}; 
    Shape(int dims) : _dimensions{dims} 
    {}; 

    virtual double getArea() {}; 
    // Because some shapes have no volume. 
    virtual double getVolume() {}; 

    void setDimensions(int dim) 
    { 
     this->_dimensions = dim; 
    }; 
    int getDimensions() 
    { 
     return this->_dimensions; 
    }; 
}; 


/** 
* Extended classes 
*/ 
class TwoDimensionalShape : public Shape 
{ 
public: 
    TwoDimensionalShape() : Shape{2} 
    {}; 
    // This should throw an error 
    double getVolume() { 
     throw logic_error("This shape ain't got area!"); 
    }; 
}; 

class ThreeDimensionalShape : public Shape 
{ 
public: 
    ThreeDimensionalShape() : Shape{3} {}; 
}; 


/** 
* Final Concrete classes extending extended classes 
*/ 
class Circle : public TwoDimensionalShape 
{ 
protected: 
    double _radius; 
public: 
    Circle(double r) : _radius{r} 
    {}; 
    double getArea() 
    { 
     // pi*r^2 
     return M_PI * pow(_radius, 2); 
    } 
}; 

class Square : public TwoDimensionalShape 
{ 
protected: 
    double _side; 
public: 
    Square(double s) : _side{s} 
    {} 
    double getArea() 
    { 
     // s^2 
     return pow(_side, 2); 
    } 
}; 

class Triangle : public TwoDimensionalShape 
{ 
protected: 
    double _base, _height; 
public: 
    Triangle(double b, double h) : _base{b}, _height{h} 
    {}; 
    double getArea() 
    { 
     // b*h/2 
     return _base * _height/2; 
    } 
}; 

class Sphere : public ThreeDimensionalShape 
{ 
protected: 
    double _radius; 
public: 
    Sphere(double r) : _radius{r} 
    {} 
    double getArea() 
    { 
     cout << 4 * M_PI * pow(_radius, 2) << endl; 
     return 4 * M_PI * pow(_radius, 2); 
    } 
    double getVolume() 
    { 
     return (4/3) * M_PI * pow(_radius, 3); 
    } 
}; 

class Cube : public ThreeDimensionalShape 
{ 
protected: 
    double _side; 
public: 
    Cube(double s) : _side{s} 
    {}; 
    double getArea() 
    { 
     // surface area = 6*a^2 
     return 6 * pow(_side, 2); 
    } 
    double getVolume() 
    { 
     // a^3 
     return pow(_side, 3); 
    } 
}; 

class Tetrahedron : public ThreeDimensionalShape 
{ 
protected: 
    double _side; 
public: 
    Tetrahedron(double s) : _side{s} 
    {}; 
    double getArea() 
    { 
     // sqrt(3)*a^2 
     return sqrt(3) * pow(_side, 2); 
    } 
    double getVolume() 
    { 
     // a^3/6sqrt(2) 
     return pow(_side, 3)/(6 * sqrt(2)); 
    } 
}; 

int main() 
{ 
    Shape arr[2]; 
    arr[0] = Circle{10}; 
    arr[1] = Sphere{10}; 

    // This one is accessing the right method. 
    cout << "Area of circle: " << arr[0].getArea() << endl; 
    // This one should access the parent, but accesses the grand parent! 
    // even if it is overridden in parent. 
    cout << "Volume of circle: " << arr[0].getVolume() << endl; 

    // Both of these are accessing methods on grand parent rather than their own!! 
    cout << "Area of sphere: " << arr[1].getArea() << endl; 
    cout << "Volume of sphere: " << arr[1].getVolume() << endl; 

    return 0; 
} 

Ich weiß nicht, warum die Array-Methoden Zugriff auf halten die großen übergeordneten Funktionen in den letzten drei Zeilen, aber die richtige Methode auf dem ersten.

+2

Sie erleben * Objekt Slicing * – WhiZTiM

+1

https://stackoverflow.com/questions/274626/what-is-object-slicing – juanchopanza

+0

owh so, ich versuche, Enkelkinder in superclass Objekt-Array zu speichern ist das Problem? – PrimeHero

Antwort

1

Sie erleben Objekt Slicing. Der Teil des Codes unten geht das:

Shape arr[2]; 
arr[0] = Circle{10}; 
arr[1] = Sphere{10}; 

Jede der Zuweisungen über den Kopierzuweisungsoperator von Shape und slices off Objekte der Unterklasse aufruft. Sie können Ihre Absicht, mit Hilfe Verweise oder Zeiger erreichen:

std::unique_ptr<Shape> arr[2]; 
arr[0] = std::make_unique<Circle>(10); 
arr[1] = std::make_unique<Sphere>(10); 
+0

Vielen Dank für das Beispiel. – PrimeHero

+0

Klasse std :: unique_ptr 'hat kein Mitglied mit dem Namen' getArea ' – PrimeHero

+0

@PrimeHero, eingewickelt in 'std :: unique_ptr', greifen Sie mit' -> 'not' .' auf die 'Shape'-Mitglieder zu. Beispiel 'arr [0] -> getArea()' – WhiZTiM

0

Dies ist ein Fall von Objekt-Slicing. Sie müssen Ihre Objekte als Zeiger setzen, vorzugsweise als std::unique_ptr<> in Ihrem Array - oder wiederum vorzugsweise ein std::vector<>

Try this:

#include <memory> 
#include <vector> 

// ... 

int main() 
{ 
    std::vector<std::unique_ptr<Shape>> vec(2); 
    vec[0] = std::make_unique<Circle>(10); 
    vec[1] = std::make_unique<Sphere>(10); 

    // This one is accessing the right method. 
    cout << "Area of circle: " << vec[0]->getArea() << endl; 
    // This one should access the parent, but accesses the grand parent! 
    // even if it is overridden in parent. 
    cout << "Volume of circle: " << vec[0]->getVolume() << endl; 

    // Both of these are accessing methods on grand parent rather than their own!! 
    cout << "Area of sphere: " << vec[1]->getArea() << endl; 
    cout << "Volume of sphere: " << vec[1]->getVolume() << endl; 

    return 0; 
} 
+0

Vektor scheint gut, ich werde mit einem Vektor gehen. – PrimeHero

Verwandte Themen