我是 Stack Overflow 的新手,正在自学 C++,但仍然是个初学者。在完成了我正在使用的书的大部分内容(可能被认为过时和/或不是一本好书)后,我决定通过自己尝试来重新强化一些概念,仅在需要时参考这本书,但我似乎被卡住了。我试图解决的概念是继承、多态性、抽象数据类型 (ADT),以及将我的类的代码分成头文件 (.h) 和 C++ 文件 (.cpp)。提前为文字墙道歉,我只想清楚具体地说明我需要在哪里。
所以,我的目标是创建简单的形状类,在适用的情况下相互继承。我有四个类:myPoly、myRectangle、myTriangle 和 mySquare。如果我正确理解了这个概念,myPoly 应该是 ADT,因为其中一种方法是纯虚函数(区域方法),因为创建 myPoly 对象并不是我希望我的类的用户做的事情。myRectangle 和 myTriangle 都派生自 myPoly,而 mySquare 又派生自 myRectangle。我还包括我计划测试我的课程的测试程序。我正在使用 Code::Blocks 10.05 并在构建我的 test.cpp 程序时不断收到以下错误:
undefined reference to 'myPoly::myPoly()'
对于 myPoly 类的方法,我得到了 42 个类似的错误。当我尝试为 myRectangle 和 myTriangle 构建 .cpp 文件时,就会发生这种情况。通过对我在这个小项目中遇到的问题进行的研究,我觉得我的包含保护或#include 语句有问题,有些东西没有被正确包含或被包含太多次。起初,我将 myPoly 的 .cpp 文件提供给 myRectangle 和 myTriangle,但在几个地方读到,包括 myPoly 的 .h 文件更有效,并且有些地方如何自动包含它的 .cpp。如果有人可以对此提供一些见解,将不胜感激。我还记得在包含语句中使用引号与使用尖括号有何不同。以下是我为我的小项目制作的所有九个文件。大多数评论对我来说都是小笔记或提醒。
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
我的矩形.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
我的矩形.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();
}
我的三角形.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
我的三角形.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()
{
}
测试.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;
}
我很好奇为什么会出现这些错误,或者为什么我所做的事情可能不被认为是好的/最佳实践,而不是仅仅收到一行代码来消除我的错误。