programa librerias funciones ejemplos comandos codigos clases cabecera archivos c++ inheritance include abstract-data-type

librerias - comandos de c++



Herencia de C++ en archivos separados usando#include y guardias de inclusiĆ³n (4)

Soy nuevo en Stack Overflow y me estoy enseñando C ++, pero aún soy un principiante. Después de completar una buena porción del libro que estoy usando (que puede considerarse obsoleto y / o no es un gran libro) decidí reforzar algunos conceptos probándolos por mi cuenta, haciendo referencia al libro solo si era necesario, pero parece estar atascado. Los conceptos que intento abordar son herencia, polimorfismo, tipos de datos abstractos (ADT) y separar el código de mis clases en archivos de encabezado (.h) y C ++ (.cpp). Lo siento de antemano por el muro de texto, solo quiero ser claro y específico donde tengo que estar.

Por lo tanto, mi objetivo es crear clases de formas simples que hereden unas de otras cuando corresponda. Tengo cuatro clases: myPoly, myRectangle, myTriangle y mySquare. myPoly, si entendí este concepto correctamente, debería ser un ADT ya que uno de los métodos es una función virtual pura (método de área), ya que crear un objeto myPoly no es algo que quisiera que hiciera un usuario de mis clases. myRectangle y myTriangle se derivan de myPoly y, a su vez mySquare se deriva de myRectangle. También incluí mi programa de prueba donde planeé probar mis clases. Estoy usando Code :: Blocks 10.05 y sigo recibiendo el siguiente error cuando construyo mi programa test.cpp:

undefined reference to ''myPoly::myPoly()''

Obtengo 42 errores similares todos para los métodos de la clase myPoly. Esto sucede cuando intento construir los archivos .cpp para myRectangle y myTriangle también. Con la investigación que traté de hacer sobre los problemas con los que me he encontrado en este pequeño proyecto siento que algo anda mal con mis guardias de inclusión o mis declaraciones #include, y algo no se está incluyendo correctamente o se está incluyendo demasiadas veces. Al principio estaba proporcionando el archivo .cpp para myPoly a myRectangle y myTriangle, pero leí en un par de lugares que incluir el archivo .h para myPoly es más eficiente y de alguna forma automáticamente incluye su .cpp. Si alguien puede darnos una idea de eso, sería muy apreciado. También recuerdo algo acerca de cómo usar las comillas en sus declaraciones de inclusión es diferente que usar los corchetes angulares. A continuación se encuentran los nueve archivos que he hecho para mi pequeño proyecto. La mayoría de los comentarios son pequeñas notas o recordatorios para mí.

myPoly.h

//Practice with inheritance, polymorphism, and Abstract Data Types //header file for Polygon class #ifndef MYPOLY_H #define MYPOLY_H class myPoly { public: //constructor //const reference pass because the values w and h don''t change and reference avoid the time it takes to copy large // objects by value (if there were any) myPoly(); myPoly(const float & w, const float & h); //destructor virtual ~myPoly(); //accessors float getWidth(); float getHeight(); void setWidth(const float & w); void setHeight(const float & h); virtual float area() = 0; private: float width, height; }; #endif

myPoly.cpp

//Practice with inheritance, polymorphism, and Abstract Data Types //implementation file for myPoly class #include "myPoly.h" //constructor myPoly::myPoly() { setWidth(10); setHeight(10); } myPoly::myPoly(const float & w, const float & h) { setWidth(w); setHeight(h); } //destructor myPoly::~myPoly() {} //accessors float myPoly::getWidth() {return width;} float myPoly::getHeight() {return height;} void myPoly::setHeight(const float & w) {width = w;} void myPoly::setWidth(const float & h) {height = h;} //pure virtual functions have no implementation //area() is handled in the header file

myRectangle.h

//Practice with inheritance, polymorphism, and Abstract Data Types //declaration file for myRectangle class #ifndef MYRECTANGLE_H #define MYRECTANGLE_H #include "myPoly.h" class myRectangle : public myPoly { public: //constructor myRectangle(); myRectangle(const float & w, const float & h); //destructor ~myRectangle(); //this doesn''t need to be virtual since the derived class doesn''t override this method float area(); }; #endif

myRectangle.cpp

//Practice with inheritance, polymorphism, and Abstract Data Types //implementaion file for the myRectangle class //get a vauge compiler/linker error if you have virtual methods that aren''t implemented (even if it ends up being just // a ''stub'' method, aka empty, like the destructor) #include "myRectangle.h" myRectangle::myRectangle() { setWidth(10); setHeight(10); } myRectangle::myRectangle(const float & w, const float & h) { setWidth(w); setHeight(h); } myRectangle::~myRectangle() { } float myRectangle::area() { return getWidth() * getHeight(); }

myTriangle.h

//Practice with inheritance, polymorphism, and Abstract Data Types //declaration file for myTriangle class #ifndef MYTRIANGLE_H #define MYTRIANGLE_H #include "myPoly.h" //imagine the triangle is a right triangle with a width and a height // |/ // | / // | / // |___/ class myTriangle : public myPoly { public: //constructors myTriangle(); myTriangle(const float & w, const float & h); //destructor ~myTriangle(); //since nothing derives from this class it doesn''t need to be virtual and in turn neither does the destructor float area(); }; #endif

myTriangle.cpp

//Practice with inheritance, polymorphism, and Abstract Data Types //implementation file for myTriangle class #include "myTriangle.h" myTriangle::myTriangle() { setWidth(10); setHeight(10); } myTriangle::myTriangle(const float & w, const float & h) { setWidth(w); setHeight(h); } myTriangle::~myTriangle() { } float myTriangle::area() { return getWidth() * getHeight() / 2; }

mySquare.h

//Practice with inheritance, polymorphism, and Abstract Data Types //declaration file for mySquare class #ifndef MYSQUARE_H #define MYSQUARE_H #include "myRectangle.cpp" class mySquare : public myRectangle { public: //constructors mySquare(); //explicity call the myRectangle constructor within this implementation to pass w as width and height mySquare(const float w); //destructor ~mySquare(); }; #endif

mySquare.cpp

//Practice with inheritance, polymorphism, and Abstract Data Types //implementation file for mySquare class #include "mySquare.h" mySquare::mySquare() { setWidth(10); setHeight(10); } mySquare::mySquare(const float w) { myRectangle::myRectangle(w, w); } mySquare::~mySquare() { }

test.cpp

//Practice with inheritance, polymorphism, and Abstract Data Types //main class that uses my shape classes and experiments with inheritance, polymorphism, and ADTs #include "myRectangle.cpp" //#include "mySquare.cpp" #include "myTriangle.cpp" #include <iostream> int main() { myPoly * shape = new myRectangle(20,20); return 0; }

Tengo mucha curiosidad por saber por qué estoy recibiendo estos errores o por qué algo que hice no se considera una buena / mejor práctica, en lugar de simplemente recibir una línea de código para que desaparezcan mis errores.


Además de lo que dijeron los demás: No estás haciendo herencia, ¿verdad? ...

Cuando tu lo hagas

class Poly { Poly(); ~Poly(); } class Rect : public Poly() { Rect(); ~Rect(); }

Debe declarar el constructor del niño de la siguiente manera:

Rect::Rect() : Poly() { }

El niño solo debe construirse después de que el padre haya terminado de construir.


Desde un punto de vista de código (al menos lo que miré), se ve bastante bien, pero:

Hay dos cosas a considerar:

  1. No incluya directamente archivos cpp. Por ejemplo, en mySquare.h, #include "myRectangle.cpp" debe ser #include "myRectangle.h" . Desea incluir las interfaces / declaraciones proporcionadas en el archivo de encabezado que le dicen al programa cómo hacer la clase, no solo las definiciones de funciones.

  2. Segundo, asegúrese de estar compilando con todos sus archivos de objeto. No conozco los bloques de código, pero si estuviera usando g ++ o algo así, querría hacer g++ main.cpp myPoly.cpp mySquare.cpp etc. para todos los archivos. Un error como este puede ocurrir si olvida myPoly.cpp, por ejemplo, porque no se incluirán definiciones para sus funciones.


Todo se ve bien, en realidad. Probablemente sea tan simple como no incluir myPoly.obj cuando vincula su programa. No estoy familiarizado con Code :: Blocks (aunque sé que es bastante popular), pero supongo que si solo, por ejemplo, hace clic en test.cpp y elige "Ejecutar", Code :: Blocks intentará crear un programa desde solo ese archivo fuente. Tendrá que incluir todos los archivos fuente relevantes en cada programa que construya.


Tus guardias de inclusión se ven bien. Si no lo fueran, lo más probable es que obtenga un error de compilación, incluida la información del número de archivo y línea. El error que ha publicado parece más un error del enlazador.

Sin embargo, hay un "problema" con su código. Como regla general, solo debe #incluir archivos .h y no archivos .cpp.

Ahora para llegar a la solución: no estoy familiarizado con Code :: Blocks. Sin embargo, espero poder brindarle información general que lo orientará en la dirección correcta. Algunos compiladores que he usado en el pasado de forma predeterminada me permitieron compilar un único archivo C ++ y ejecutar el programa. Para compilar un programa con más de un archivo, tuve que crear un proyecto. (La mayoría de los compiladores modernos lo obligan a crear un proyecto desde el principio.) Con esto en mente, le sugiero que consulte cómo crear un proyecto para su programa en Code :: Blocks.