使用#include 和包含保护的单独文件中的 C++ 继承
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11747954/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ Inheritance in Separate Files Using #include and Inclusion Guards
提问by RIBdot
I am new to Stack Overflow and am teaching myself C++, but am still quite a beginner. After completing a nice chunk of the book I am using (which may be considered out dated and/or not a great book) I decided to re-enforce some concepts by trying them on my own, referencing the book only if needed, but I appear to be stuck. The concepts I am trying to tackle are inheritance, polymorphism, abstract data types (ADT), and separating the code for my classes into header files (.h) and C++ file (.cpp). Sorry in advance for the wall of text, I just want to be clear and specific where I need to be.
我是 Stack Overflow 的新手,正在自学 C++,但我仍然是一个初学者。在完成了我正在使用的一本书的大部分内容(可能被认为是过时的和/或不是一本好书)后,我决定通过自己尝试来重新强化一些概念,仅在需要时参考这本书,但我似乎被卡住了。我试图解决的概念是继承、多态性、抽象数据类型 (ADT),以及将我的类的代码分成头文件 (.h) 和 C++ 文件 (.cpp)。提前为文字墙感到抱歉,我只是想清楚和具体地说明我需要去的地方。
So, my goal is to create simple shape classes that inherit from one another where applicable. I have four classes: myPoly, myRectangle, myTriangle, and mySquare. myPoly, if I understood this concept correctly, should be an ADT since one of the methods is a pure virtual function (area method), since creating a myPoly object isn't something I would want a user of my classes to do. myRectangle and myTriangle both derive from myPoly and in turn mySquare derives from myRectangle. I've also included my test program where I planned on testing my classes. I am using Code::Blocks 10.05 and keep getting the following error when I build my test.cpp program:
所以,我的目标是创建简单的形状类,在适用的情况下相互继承。我有四个类:myPoly、myRectangle、myTriangle 和 mySquare。myPoly,如果我正确理解这个概念,应该是 ADT,因为其中一个方法是纯虚函数(区域方法),因为创建 myPoly 对象不是我希望我的类的用户做的事情。myRectangle 和 myTriangle 都源自 myPoly,而 mySquare 又源自 myRectangle。我还包括了我的测试程序,我计划在其中测试我的课程。我正在使用 Code::Blocks 10.05 并在构建 test.cpp 程序时不断收到以下错误:
undefined reference to 'myPoly::myPoly()'
I get 42 similar errors all for the methods of the myPoly class. This happens when I try to build the .cpp files for myRectangle and myTriangle too. With the research I tried to do on the problems I been running into with this little project I feel like something is wrong with my inclusion guards or my #include statements, and something isn't getting included properly or is getting included too many times. At first I was providing the .cpp file for myPoly to myRectangle and myTriangle, but read in a couple of places that including the .h file for myPoly is more efficient and some how automatically include its .cpp. If anyone can provide some insight on that, it would be greatly appreciated. I also remember something about how using quotes in your inclusion statements is different than using the angle brackets. Below are all nine files that I have made for my little project. Most of the comments are little notes or reminders to me.
对于 myPoly 类的方法,我得到了 42 个类似的错误。当我尝试为 myRectangle 和 myTriangle 构建 .cpp 文件时也会发生这种情况。通过对我在这个小项目中遇到的问题进行的研究,我觉得我的包含守卫或我的 #include 语句有问题,并且某些内容没有被正确包含或被包含太多次。起初,我将 myPoly 的 .cpp 文件提供给 myRectangle 和 myTriangle,但在几个地方读到,包括 myPoly 的 .h 文件更有效,以及一些如何自动包含其 .cpp 的地方。如果有人能对此提供一些见解,将不胜感激。我还记得在包含语句中使用引号与使用尖括号有何不同。下面是我为我的小项目制作的所有九个文件。大多数评论都是对我的小笔记或提醒。
myPoly.h
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
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
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
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
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
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
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
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
测试.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;
}
I am very curious as to why I am getting these errors or why something I did may not be considered good/best practice, as opposed to just receiving a line of code to make my errors go away.
我很好奇为什么我会收到这些错误,或者为什么我所做的事情可能不被认为是好的/最佳实践,而不是仅仅收到一行代码来消除我的错误。
采纳答案by Code-Apprentice
Your inclusion guards look fine. If they were not, you would most likely get a compiler error, including file and line number information. The error you posted seems more like a linker error.
你的包容守卫看起来不错。如果不是,您很可能会收到编译器错误,包括文件和行号信息。您发布的错误似乎更像是链接器错误。
However, there is one "problem" with your code. As a general rule, you should only #include
.h files and not .cpp files.
但是,您的代码存在一个“问题”。作为一般规则,您应该只使用#include
.h 文件而不是 .cpp 文件。
Now to get to the solution: I am unfamiliar with Code::Blocks myself. However, I hope I can give some general information that will point you in the right direction. Some compilers I have used in the past by default allowed me to compile a single C++ file and run the program. To compile a program with more than one file, I had to create a project. (Most modern compilers force you to create a project from the start.) With this in mind, I would suggest you check out how to create a project for your program in Code::Blocks.
现在进入解决方案:我自己不熟悉 Code::Blocks。但是,我希望我可以提供一些一般信息,为您指明正确的方向。我过去使用的一些编译器默认允许我编译单个 C++ 文件并运行程序。要编译包含多个文件的程序,我必须创建一个项目。(大多数现代编译器强制您从一开始就创建一个项目。)考虑到这一点,我建议您查看如何在 Code::Blocks 中为您的程序创建一个项目。
回答by John Humphreys - w00te
From a code stand point (at least what I looked through), it looks pretty good, but:
从代码的角度来看(至少我看过的),它看起来不错,但是:
There are two things to consider:
有两件事需要考虑:
Don't directly include cpp files. For example, in mySquare.h,
#include "myRectangle.cpp"
should be#include "myRectangle.h"
. You want to be including the interface/declarations provided in the header file that tell the program how to make the class, not just the function definitions.Second, make sure you're compiling with all your object files. I don't know code blocks, but if you were using g++ or something like that, you'd want to do
g++ main.cpp myPoly.cpp mySquare.cpp etc.
for all files. An error like this may happen if you forget myPoly.cpp, for example, because no definitions for its functions would be included.
不要直接包含 cpp 文件。例如,在 mySquare.h 中,
#include "myRectangle.cpp"
应该是#include "myRectangle.h"
. 您希望包含头文件中提供的接口/声明,这些接口/声明告诉程序如何创建类,而不仅仅是函数定义。其次,确保使用所有目标文件进行编译。我不知道代码块,但如果你使用 g++ 或类似的东西,你会想要
g++ main.cpp myPoly.cpp mySquare.cpp etc.
为所有文件做。例如,如果您忘记了 myPoly.cpp,可能会发生这样的错误,因为将不包含其函数的定义。
回答by Ernest Friedman-Hill
Everything looks fine, actually. It is probably just as simple as not including myPoly.obj when you link your program. I am not familiar with Code::Blocks (although I know it's fairly popular) but I assume if you just, for example, click on test.cpp and choose "Run", that Code::Blocks will try to build a program from just that one source file. You'll need to include all the relevant source files in each program that you build.
事实上,一切看起来都很好。这可能就像在链接程序时不包含 myPoly.obj 一样简单。我不熟悉 Code::Blocks(虽然我知道它很受欢迎)但我假设如果你只是,例如,点击 test.cpp 并选择“运行”,Code::Blocks 将尝试构建一个程序只是那个源文件。您需要在您构建的每个程序中包含所有相关的源文件。
回答by gibertoni
Additionally to what the otehr guys said: You are not doing inheritance right...
除了 otehr 人所说的:你没有正确地继承......
When you do
当你做
class Poly
{
Poly();
~Poly();
}
class Rect : public Poly()
{
Rect();
~Rect();
}
You need to declare the child's constructor the following way:
您需要通过以下方式声明孩子的构造函数:
Rect::Rect() : Poly()
{
}
The child must only be constructed after the father has finished constructing.
只有在父亲完成构建之后才能构建孩子。