Как добиться многоуровневого наследования с помощью классов

Я пытаюсь сделать многоуровневое наследование от класса Shape к классам Rectangle, Circle и Triangle. От Rectangle мне нужно наследовать класс Square и распечатать площадь, информацию и т. д., а также Ellipse от Circle и Isosceles от Triangle. Пока что мои первые унаследованные классы работают нормально, но всякий раз, когда я пытаюсь заставить работать класс «внуков», я не могу заставить его работать. Я понятия не имею, что я могу делать неправильно. Вот код:

 #include <iostream>
 using namespace std;

 class Shape{
 protected:
 string name;
 float area;

 public:
 Shape(string nm):name(nm){}

 //Getters
 string     getName(){    return name;    }
 float    getArea(){}

 //Setters
 virtual void    setArea(){}

 //Print
 virtual void printInfo()
 {
    cout << "Name: " << name << " Color: " << endl;
}

};

class Rectangle :  public Shape{
private:
float length, width;

public:
Rectangle(string nm, float l, float w):Shape::Shape(nm), length(l), width(w){}
Shape::getName();

//Setters
void setArea(){ area = length*width; }

void printInfo(){
    //Shape::printInfo();
    cout << "Name: " << name << " L: " << length << " W: " << width << " A: " << area << endl;
}
};

class Square : public Rectangle{

private:
float length;

public:
Square(string nm, float l):length(l),Rectangle::Rectangle(nm){}
float     getLength(){return length;}

//Setters
void setArea(){ area = length *length; }

};

class Circle : public Shape{
private:
float radius;
const float pi = 3.0;

public:
Circle(string nm, float r):Shape::Shape(nm), radius(r){}

//Setters
void setArea(){ area = pi*radius*radius; }

void printInfo(){
    //Shape::printInfo();
    cout << "Name: " << name << " R: " << radius << " A: " << area <<      endl;
}
};

 //class Ellipse : public Circle{
 //
 //private:
 //    float length, width, radius1, radius2;
   //
//public:
//    Ellipse(string nm, int clr, float l, float w);
//
//    //Setters
//void setArea(){ area = radius1 * radius2; }
//
//};

class Triangle : public Shape{
private:
float a, base, c, height;

public:
Triangle(string nm, float a, float b, float c, float h):Shape::Shape(nm), a(a), base(b), c(c), height(h){}

//Setters
void setArea(){ area = (base*height)/2; }

void printInfo(){
    //Shape::printInfo();
    cout << "Name: " << name << " Color: " << " A: " << a << " Base: " << base <<  " C: " << c  << " H: " << height << " P: " << " A: " << area << endl;
}
};

//class Isosceles : public Triangle{
//
//private:
//    float base, height;
//
//public:
//    Isosceles(string nm, int clr, float l, float w);
//
//    //Setters
//    void setArea(){ area = (base*height)/2; }
//
//}; 

int main() {

Rectangle r("Rectangle", 10, 20);
Circle c("Circle", 1);
Triangle tt("Triangle", 2, 2, 3, 3);
Square ss("Square", 10);

Shape* s;
Shape* t;
Shape* u;
Shape* v;
s = &r;
t = &c;
u = &tt;
v = &ss;

//Set and print area of Rectangle
s->setArea();
s->printInfo();

//Set and print area of Circle
t->setArea();
t->printInfo();

//Set and print area of Triangle
u->setArea();
u->printInfo();

//Set and print area of Rectangle
v->setArea();
v->printInfo();


return 0;
}

Я получаю сообщение об ошибке при настройке класса Square здесь:

class Square : public Rectangle{

private:
float length;

public:
Square(string nm, float l):length(l),Rectangle::Rectangle(nm){}

Я закомментировал классы Ellipse и Isosceles, чтобы правильно настроить Square и не работать с ними позже. Это мой первый вопрос, поэтому, если что-то не так, пожалуйста, дайте мне знать. Спасибо за помощь.


person Bran_Ortiz    schedule 18.10.2018    source источник
comment
Должно быть некоторое указание на то, что не так, иначе как вы узнаете, что у вас проблема? Есть ли ошибка при компиляции вашей программы? Не работает ли он, когда вы его выполняете, и если нет, то что он делает?   -  person Steve    schedule 18.10.2018
comment
Я получаю сообщение об ошибке при настройке класса Square. В чем ошибка?   -  person Steve    schedule 18.10.2018
comment
Скорее всего, вам нужно изменить Square(string nm, float l):length(l),Rectangle::Rectangle(nm){} на что-то вроде Square(string nm, float l): Rectangle(nm), length(l) {}.   -  person Steve    schedule 18.10.2018
comment
Конечно, конструктор Rectangle() принимает более одного параметра, так что это даже не ответ...   -  person Steve    schedule 18.10.2018
comment
В некоторых случаях ваше наследование основано на количестве атрибутов (эллипс против круга), а в других случаях — на отношении IS-A (прямоугольник против квадрата). На практике ни один из них не подходит, и в любом случае было бы лучше использовать один уровень (например, квадрат на том же уровне, что и прямоугольник) или просто сохранить только более общие формы (например, прямоугольник, эллипс и треугольник).   -  person Phil1970    schedule 18.10.2018
comment
Извините, что не ответил, я получил ошибку компилятора, что Rectangle::Rectangle не найден или что-то в этом роде, но предложение Билала Салима сработало   -  person Bran_Ortiz    schedule 18.10.2018


Ответы (1)


Кажется, в вашем классе Square я нашел одну ошибку...

Попробуйте сделать следующее с вашим квадратным конструктором:

Square(string nm, float l):length(l),Rectangle::Rectangle(nm, l, l){} 

В отличие от того, что у вас было... это исправит ошибки, которые вы получаете с классом Square.

Причина различия в том, что когда вы передавали аргументы конструктору Rectangle из конструктора Square, вы оставляли некоторые аргументы неинициализированными (в конструкторе Rectangle).

person Bilal Saleem    schedule 18.10.2018
comment
Ого, я честно много вариантов перепробовал, кроме этого. Это дает мне некоторые предупреждения, но, по крайней мере, программа компилируется. Большое спасибо. - person Bran_Ortiz; 18.10.2018