It is necessary to develop a hierarchy of classes of spatial figures: a cone, a parapiped, a cube, a sphere, an ellipsoid, a cylinder. How is it better to organize, there, what class to take for the base and TP?

  • Very bad answer. The inheritance relationship is essentially the "is" relationship. Therefore, the rectangle from the square should not be inherited. - dzhioev
  • 3
    What are you going to do with the objects of your classes? As they say in the village, it depends. - BuilderC
  • 2
    habrahabr.ru/blogs/programming/123014 get acquainted, very useful - Viacheslav
  • square as a particular rectangle shape, I meant to highlight the main types of shapes and inherit marching from them. Looked at the link (the one that is in question), IMHO, it is immediately obvious that the circle is a special case of an ellipse, i.e. an ellipse with the same radius. And to distinguish the interface "body" is the wrong level of abstraction, so you can take a point, why is there .... and if you take it, so let it keep the type and name =) - Gorets
  • The rectangle from the square is really not worth it. And vice versa is possible (square is a special case of a rectangle, and a ball is a special case of an ellipsoid), but why? In this question, the volumetric figures can be inherited from those flat ones for which they are the bodies of revolution. A cylinder from a rectangle, an ellipsoid from an ellipse, a cone from a triangle, etc. But without understanding the multitude of tasks for which all this requires such a development, the matter is empty. - avp

4 answers 4

At the very top of the hierarchy, an abstract class, let's say, a Figure with a set of virtual functions for working with objects, such as drawing and so on.

At the second level of a figure with one parameter: a cube (side) and a sphere (radius)

At the third level, figures with 2 parameters with inheritance from 1-parameter figures, for example, an ellipsoid, a cylinder and a cone are inherited from a sphere, a parallelepiped from a cube, etc.

  • one
    It is usually more convenient on the contrary - to make a particular (cube) out of the general (parallelepiped). By the way, do not draw, how to get a cone from a sphere? - avp
  • This is not a matter of convenience, but a matter of class members. The sphere has a 1st member = protected radius, and a cone of two members: radius and height, with the radius inheriting from the sphere. Saving space there. Not? - Barmaley
  • one
    Well, if the goal of designing a hierarchy of classes is to consider saving memory for data, then Yes! - avp
  • It is impossible to inherit a rectangle from a square, it violates the Principle of Lisk (LSP) substitution. - Abyx

Geometric objects are one of the special cases. Take a set of flat shapes: Square - Rectangle - Parallelogram - Rhombus

  1. In geometry, a square is a special case of a rectangle and a rhombus, a rectangle is a special case of a parallelogram, and a rhombus is a special case of a parallelogram. We will not be able to implement such a chain. OOP extends inheritance, i.e. we can add something to the heir, but we cannot cut out the excess.

  2. In OOP (expanding functionality). A parallelogram is inherited from a rhombus or a rectangle, a rhombus is inherited from a square, a rectangle is inherited from a square. Because an instance of a derived class is also an instance of a base class, then in this context we get, for example, the following statement: any rectangle is a square. And this contradicts the geometric definition (and logic).

With solid shapes, lines, surfaces, etc. exactly the same thing.

Thus, we can select an abstract class / interface as a base class of geometric objects, for example, GeometricSolid, and define in a set of general methods for calculating the volume and surface area, all shapes have this. The figures themselves inherit from this class / interface, all on the same level . Only in this form, your model will not contradict the OOP or geometry.

    For the base, you can select the interface " Π’Π΅Π»ΠΎ ". Interfaces in C++ are abstract classes.

    For example, if these are classes for a visualization system, then it makes sense to declare a draw method:

     class body { ... virtual void draw() = 0; ... }; 

      Here's my solution, really for you. Take remake for yourself

       #include <iostream> #include <iomanip> #include <conio.h> #include <string.h> #define M_PI 3.14159265358979323846 using namespace std; /*================================================ Π‘ΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΡŽ классов Π’ΠΎΡ‡ΠΊΠ°-ΠšΡ€ΡƒΠ³-ΠšΠΎΠ½ΡƒΡ. ΠšΠΎΠ½ΡƒΡ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ опрСдСлСния объСма. ПослСдниС Π΄Π²Π° класса Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΈΠΌΠ΅Ρ‚ΡŒ конструкторы. ===================================================*/ class Point { //Класс Point public: int x; int y; }; class Circle : public Point { public: float r1; //радиус ΠΊΡ€ΡƒΠ³Π° Circle(float r1) { r1 = r1; } }; class Cone : public Circle { public: double H; double volume; Cone(double r1, double h1):Circle(r1) { H = h1; } void calculate_volume() { volume = (1.0 / 3.0) * H * M_PI; //Π€ΠΎΡ€ΠΌΡƒΠ»Π° для нахоТдСния объСма конуса } }; /*================================================ Π‘ΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ MAIN, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ создаСтся Π΄Π²Π° конуса, опрСдСляСтся ΠΊΠ°ΠΊΠΎΠΉ ΠΈΠ· конусов мСньшС, Π° Ρ‚Π°ΠΊΠΆΠ΅ Π²Ρ…ΠΎΠ΄ΠΈΡ‚ Π»ΠΈ мСньший конус Π² больший. Π’Π°ΠΊΠΆΠ΅ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ всС характСристики создаваСмых ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ². ===================================================*/ void main() { setlocale(LC_ALL, "rus"); //настраиваСм локаль setlocale(LC_NUMERIC, "C"); /*================================================ Π’Π°ΠΊΠΈΠ΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹, Ρ‡Ρ‚ΠΎΠ±Ρ‹ мСньший конус ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Π²Ρ…ΠΎΠ΄ΠΈΠ» Π² больший ===================================================*/ Cone m(5, 6); //больший конус Cone n(5, 6); //мСньший конус /*================================================ Π’Π°ΠΊΠΈΠ΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹, Ρ‡Ρ‚ΠΎΠ±Ρ‹ мСньший конус Π½Π΅ Π²Ρ…ΠΎΠ΄ΠΈΠ» Π² больший ===================================================*/ //Cone m(4, 6); //больший конус //Cone n(6, 4); //мСньший конус m.calculate_volume(); //считаСм объСм ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ конуса n.calculate_volume(); //считаСм объСм Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ конуса cout Β« "ОбъСм ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ конуса Ρ€Π°Π²Π΅Π½: " Β« m.volume Β« " кубичСских Π΅Π΄ΠΈΠ½ΠΈΡ†" Β« endl; cout Β« "ОбъСм Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ конуса Ρ€Π°Π²Π΅Π½: " Β« n.volume Β« " кубичСских Π΅Π΄ΠΈΠ½ΠΈΡ†" Β« endl; cout Β« "-------------------------------------------" Β« endl; //ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°, Ссли ΠΎΠ±ΡŠΠ΅ΠΌΡ‹ конусов Ρ€Π°Π·Π½Ρ‹Π΅ if (m.volume > n.volume) { cout Β« "МСньший конус ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Π²Ρ…ΠΎΠ΄ΠΈΡ‚ Π² больший конус..." Β« endl; } else if (m.volume = n.volume) { cout Β« "ΠžΠ±ΡŠΠ΅ΠΌΡ‹ Π΄Π²ΡƒΡ… конусов Ρ€Π°Π²Π½Ρ‹" Β« endl;; } else { cout Β« "МСньший конус Π½Π΅ Π²Ρ…ΠΎΠ΄ΠΈΡ‚ Π² большой конус..." Β« endl; } cout Β« "--------------------------------------------" Β« endl; cout Β« "Π’Ρ‹Π²ΠΎΠ΄ΠΈΠΌ всС характСристики созданных ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Π½Π° экран: " Β« endl; cout Β« setw(25) Β« "Радиус ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ конуса: " Β« m.r1 Β« setprecision(6) Β« endl; cout Β« setw(25) Β« "Высота ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ конуса: " Β« mH Β« endl; cout Β« setw(25) Β« "Радиус Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ конуса: " Β« n.r1 Β« setprecision(6) Β« endl; cout Β« setw(25) Β« "Высота Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ конуса: " Β« nH Β« endl; system("pause"); }