Hierarquia Forma. Implemente a hierarquia Forma

projetada no Exercício 20.7 (que é baseada na hierarquia

da Figura 20.3). Cada FormaBidimensional deverá

conter a função retArea para calcular a área da forma

bidimensional. Cada FormaTridimensional deverá ter

funções-membro retArea e retVolume para calcular a

área e o volume, respectivamente, da forma tridimensional.

Crie um programa que use um vetor de ponteiros

Forma para objetos de cada classe concreta na hierarquia.

O programa deverá imprimir o objeto ao qual cada elemento

vetor aponta. Além disso, no loop que processa

todas as formas no vetor, determine se cada forma é uma

FormaBidimensional ou uma FormaTridimensional.

Se a forma for uma FormaBidimensional, mostre

sua área. Se a forma for uma FormaTridimensional,

mostre sua área e seu volume.

Passo 1

Vamos implementar a seguinte hierarquia Shape:

'slader'

Em primeiro lugar, vamos fazer a classe base "abstract/interface" Shape que será puramente virtual e armazenará apenas bibliotecas:

#ifndef H_SHAPE_H

#define H_SHAPE_H

#include cmath>

class Shape {

public:

virtual double getArea() const = 0;

};

Forma bidimensional

Esta classe será uma classe abstrata pura com a função getArea():

#ifndef H_TWODIMENSIONALSHAPE_H

#define H_TWODIMENSIONALSHAPE_H

#include "Shape.h"

class TwoDimensionalShape : public Shape {

public:

virtual double getArea() const = 0;

};

Elipse

Esta classe possuirá dois membros de dados protegidos representando comprimentos de eixo. Os membros de dados serão protegidos porque a classe derivada Circle também deve poder usá-los livremente (ambos os valores são iguais ao raio do círculo).

#ifndef H_ELLIPSE_H

#define H_ELLIPSE_H

#include "TwoDimensionalShape.h"

class Ellipse : public TwoDimensionalShape {

public:

Ellipse(double a, double b);

double getArea() const;

protected:

double a;

double b;

};

A área da elipse é igual ao produto do eixo menor e maior multiplicado por pi:

A   =   π a b

A implementação:

#include cmath>

#include "Ellipse.h"

Ellipse::Ellipse(double a, double b) : a(a), b(b) {}

double Ellipse::getArea() const {

return M_PI * a * b;

}

Passo 2

Como um círculo é uma elipse com um eixo maior/menor igual ao raio do círculo, podemos definir os dois valores para o raio e reutilizar toda a classe da seguinte maneira:

#ifndef H_CIRCLE_H

#define H_CIRCLE_H

#include "Ellipse.h"

class Circle : public Ellipse {

public:

explicit Circle(double radius);

};

#en

Fórmula da área do círculo:

A = r 2 π

A implementação:

#include "Circle.h"

Circle::Circle(double radius) : Ellipse(radius, radius) {}

Polígono

Esta classe servirá como uma classe vazia pai de rótulo:

#ifndef H_POLYGON_H

#define H_POLYGON_H

#include "TwoDimensionalShape.h"

class Polygon : public TwoDimensionalShape {

};

#endif

Observação: excluiremos a classe n-gon shapes para simplificar a tarefa.

Triângulo

A classe triângulo representará uma forma de triângulo e calculará a área por meio de uma fórmula genérica:

#ifndef H_TRIANGLE_H

#define H_TRIANGLE_H

#include "Polygon.h"

class Triangle : public Polygon {

public:

Triangle(double a, double b, double c);

double getArea() const;

protected:

double a;

double b;

double c;

};

#endif

Para calcular a área, usaremos a fórmula de Heron com o diâmetro s = a + b + c 2

A = s s - a s - b s - c

#include "Triangle.h"

Triangle::Triangle(double a, double b, double c) : a(a),

b(b),

c(c) {}

double Triangle::getArea() const {

double s = (a + b + c) / 2;

return sqrt(s * (s - a) * (s - b) * (s - c));

}

Passo 3

Agora vamos derivar outras classes da classe Triangle.

Os tipos de triângulos que vamos incluir são os triângulos equiláteros e isósceles porque dependem dos comprimentos dos lados, enquanto os demais tipos dependem dos ângulos, que não incluiremos para simplificar a tarefa.

Triângulo Equilátero

Declaração de classe:

#ifndef H_EQUILATERALTRIANGLE_H

#define H_EQUILATERALTRIANGLE_H

#include "Triangle.h"

class EquilateralTriangle : public Triangle {

public:

explicit EquilateralTriangle(double a);

};

#endif

Implementação da classe:

#include "EquilateralTriangle.h"

EquilateralTriangle::EquilateralTriangle(double a)

: Triangle(a, a, a) {}

Triângulo isósceles

Declaração de classe:

#ifndef H_ISOSCELESTRIANGLE_H

#define H_ISOSCELESTRIANGLE_H

#include "Triangle.h"

class IsoscelesTriangle : public Triangle {

public:

explicit IsoscelesTriangle(double a, double b);

};

#endif

Passo 4

Implementação da classe:

#include "IsoscelesTriangle.h"

IsoscelesTriangle::IsoscelesTriangle(double a, double b)

: Triangle(a, a, b) {}

Quadrilátero

Esta classe servirá como uma classe vazia pai:

#ifndef H_QUADRILATERAL_H

#define H_QUADRILATERAL_H

#include "Polygon.h"

class Quadrilateral : public Polygon {

};

#endif

trapézio

A classe vai armazenar os lados da base da forma com a adição da altura (distância entre os lados paralelos), que será usada no cálculo da área:

#ifndef H_TRAPEZOID_H

#define H_TRAPEZOID_H

#include "Quadrilateral.h"

class Trapezoid : public Quadrilateral {

public:

Trapezoid(double base1, double base2, double height);

double getArea() const;

private:

double base1;

double base2;

double height;

};

#endif

Fórmula que usaremos para calcular a área do trapézio (a e b são lados da base):

A = a + b 2 ⋅ h

#include "Trapezoid.h"

Trapezoid::Trapezoid(double base1, double base2,

double height)

: base1(base1), base2(base2), height(height) {}

double Trapezoid::getArea() const {

return ((base1 + base2) / 2) * height;

}

Pipa

Para esta classe, armazenaremos apenas os comprimentos diagonais:

#ifndef H_KITE_H

#define H_KITE_H

#include "Quadrilateral.h"

class Kite : public Quadrilateral {

public:

Kite(double p, double q);

double getArea() const;

private:

double p;

double q;

};

#endif

Passo 5

Fórmula da área de uma pipa:

A = p q 2

#include "Kite.h"

Kite::Kite(double p, double q) : p(p), q(q) {}

double Kite::getArea() const {

return p * q / 2;

}

Retângulo

Para simplificar a tarefa, derivaremos apenas as classes Rectangle e Square.

#ifndef H_RECTANGLE_H

#define H_RECTANGLE_H

#include "Quadrilateral.h"

class Rectangle : public Quadrilateral {

public:

Rectangle(double a, double b);

double getArea() const;

protected:

double a;

double b;

};

#endif

A=ab

#include "Rectangle.h"

Rectangle::Rectangle(double a, double b) : a(a), b(b) {}

double Rectangle::getArea() const {

return a * b;

}

Quadrado

Vamos simplesmente inicializar tanto Rectangle::a quanto Rectangle::b para um único comprimento e reutilizar a classe inteira:

#ifndef H_SQUARE_H

#define H_SQUARE_H

#include "Rectangle.h"

class Square : public Rectangle {

public:

explicit Square(double a);

};

#endif

A implementação:

#include "Square.h"

Square::Square(double a) : Rectangle(a, a) {}

Passo 6

Forma Tridimensional

A declaração de classe (classe abstrata pura):

#ifndef H_THREEDIMENSIONALSHAPE_H

#define H_THREEDIMENSIONALSHAPE_H

#include "Shape.h"

class ThreeDimensionalShape : public Shape {

public:

virtual double getSurfaceArea() const = 0;

virtual double getVolume() const = 0;

};

#endif

Cone

A classe armazenará o raio e a altura da forma do cone:

#ifndef H_CONE_H

#define H_CONE_H

#include "ThreeDimensionalShape.h"

class Cone : public ThreeDimensionalShape {

public:

Cone(double radius, double height);

double getArea() const;

double getVolume() const;

private:

double radius;

double height;

};

#endif

Área de superfície do cone:

A = π r r + h 2 + r 2

Volume do cone:

V = π r 2 h 3

#include "Cone.h"

Cone::Cone(double radius, double height)

: radius(radius), height(height) {}

double Cone::getArea() const {

return M_PI * radius * (radius

+ sqrt(pow(height, 2.0) + pow(radius, 2.0)));

}

double Cone::getVolume() const {

return M_PI * pow(radius, 2.0) * height / 3;

}

Poliedro

Esta classe servirá como uma classe vazia pai de rótulo:

#ifndef SLADERC_POLYHEDRON_H

#define SLADERC_POLYHEDRON_H

#include "ThreeDimensionalShape.h"

class PolyHedron : public ThreeDimensionalShape {

};

#endif

Nota: Vamos pular a derivação do prisma e incluir apenas a derivação do cubo de sólidos platônicos para simplificar a tarefa.

Pirâmide

A classe conterá o comprimento, a largura e a altura da forma da pirâmide:

#ifndef H_PYRAMID_H

#define H_PYRAMID_H

#include "PolyHedron.h"

class Pyramid : public PolyHedron {

public:

Pyramid(double length, double width, double height);

double getArea() const;

double getVolume() const;

private:

double length;

double width;

double height;

};

#endif

Passo 7

Área de superfície da pirâmide:

A = l w + l w 2 2 + h 2 + w l 2 2 + h 2

#include "Pyramid.h"

Pyramid::Pyramid(double length, double width,

double height) : length(length),

width(width),

height(height) {}

double Pyramid::getArea() const {

return length * width + length

* sqrt(pow((width / 2), 2.0)

+ pow(height, 2.0))

+ width * sqrt(pow((length / 2), 2.0)

+ pow(height, 2.0));

}

double Pyramid::getVolume() const {

return length * width * height / 3;

}

Cubo

Declaração de classe:

#ifndef H_CUBE_H

#define H_CUBE_H

#include "PolyHedron.h"

class Cube : public PolyHedron {

public:

explicit Cube(double a);

double getArea() const;

double getVolume() const;

private:

double a;

};

#endif

Área de superfície do cubo:

A = 6 a 2

Volume do cubo:

V = a 3

#include "Cube.h"

Cube::Cube(double a) : a(a) {}

double Cube::getArea() const {

return 6 * pow(a, 2.0);

}

double Cube::getVolume() const {

return pow(a, 3.0);

}

Cilindro

Declaração de classe:

#ifndef H_CYLINDER_H

#define H_CYLINDER_H

#include "ThreeDimensionalShape.h"

class Cylinder : public ThreeDimensionalShape {

public:

Cylinder(double radius, double height);

double getArea() const;

double getVolume() const;

private:

double radius;

double height;

};

#endif

Área de superfície do cilindro:

A = 2 π r h + 2 π r 2

Volume do cilindro:

V = π r 2 h

#include "Cylinder.h"

Cylinder::Cylinder(double radius, double height) : radius(

radius), height(height) {}

double Cylinder::getArea() const {

return 2 * M_PI * radius * height

+ 2 * M_PI * pow(radius, 2.0);

}

double Cylinder::getVolume() const {

return M_PI * pow(radius, 2.0) * height;

}

#include "Cylinder.h"

Cylinder::Cylinder(double radius, double height) : radius(

radius), height(height) {}

double Cylinder::getArea() const {

return 2 * M_PI * radius * height

+ 2 * M_PI * pow(radius, 2.0);

}

double Cylinder::getVolume() const {

return M_PI * pow(radius, 2.0) * height;

}

Área de superfície da esfera:

A = 4 π r 2

Volume da esfera:

V = 4 π r 3 3

#include "Sphere.h"

Sphere::Sphere(double radius) : radius(radius) {}

double Sphere::getArea() const {

return 4 * M_PI * pow(radius, 2.0);

}

double Sphere::getVolume() const {

return 4 * M_PI * pow(radius, 3.0) / 3;

}

Por fim, o arquivo principal para fins de demonstração.

Cabeçalho do arquivo (incluindo as "folhas" da árvore hierárquica é o mínimo):

#include iostream>

#include

#include "Circle.h"

#include "EquilateralTriangle.h"

#include "IsoscelesTriangle.h"

#include "Trapezoid.h"

#include "Kite.h"

#include "Square.h"

#include "Cone.h"

#include "Pyramid.h"

#include "Cube.h"

#include "Cylinder.h"

#include "Sphere.h"

using namespace std;

...

Declare e inicialize objetos e coloque-os em um vetor:

int main()

{

vector shapes;

Ellipse ellipse(1, 2);

Circle circle(13);

EquilateralTriangle equilateralTriangle(13);

IsoscelesTriangle isoscelesTriangle(13, 27);

Trapezoid trapezoid(5, 4, 3);

Kite kite(13, 27);

Rectangle rectangle(1, 2);

Square square(2);

Cone cone(6, 13);

Pyramid pyramid(1, 2, 3);

Cube cube(13);

Cylinder cylinder(13, 27);

Sphere sphere(13);

shapes.push_back(&ellipse);

shapes.push_back(&circle);

shapes.push_back(&equilateralTriangle);

shapes.push_back(&isoscelesTriangle);

shapes.push_back(&trapezoid);

shapes.push_back(&kite);

shapes.push_back(&rectangle);

shapes.push_back(&square);

shapes.push_back(&cone);

shapes.push_back(&pyramid);

shapes.push_back(&cube);

shapes.push_back(&cylinder);

shapes.push_back(&sphere);

...

}

Por fim, itere pelo vetor usando o tipo automático. Para cada objeto, verifique se o objeto é bidimensional ou tridimensional usando o valor de retorno da conversão dinâmica dos objetos da seguinte maneira:

int main()

{

...

for (auto & shape : shapes)

{

if (dynamic_castTwoDimensionalShape*>(shape))

{

auto* tmp = (TwoDimensionalShape*)shape;

cout two-dimensional shape" endl

getArea() endl;

}

else

{

auto* tmp = (ThreeDimensionalShape*)shape;

cout three-dimensional shape" endl

area: " getArea()

endl

getVolume()

endl;

}

cout endl;

}

}

Resposta

Ver o desenvolvimento!!