C++;在单独的文件中使用#包含和包含保护进行继承 我是一个新的堆栈溢出,我是自学C++的,但我还是初学者。在完成了我正在使用的一本书(可能被认为是过时的和/或不是一本好书)的一大块之后,我决定重新实施一些概念,自己尝试一下,只在需要时参考这本书,但我似乎被卡住了。我试图解决的概念是继承、多态、抽象数据类型(ADT),并将类的代码分割为头文件(.h)和C++文件(.cp)。对不起提前墙的文字,我只是想明确和具体的我需要在哪里

C++;在单独的文件中使用#包含和包含保护进行继承 我是一个新的堆栈溢出,我是自学C++的,但我还是初学者。在完成了我正在使用的一本书(可能被认为是过时的和/或不是一本好书)的一大块之后,我决定重新实施一些概念,自己尝试一下,只在需要时参考这本书,但我似乎被卡住了。我试图解决的概念是继承、多态、抽象数据类型(ADT),并将类的代码分割为头文件(.h)和C++文件(.cp)。对不起提前墙的文字,我只是想明确和具体的我需要在哪里,c++,inheritance,include,abstract-data-type,C++,Inheritance,Include,Abstract Data Type,因此,我的目标是创建简单的shape类,这些类在适用的情况下可以相互继承。我有四个类:myPoly、myRectangle、myTriangle和mySquare。如果我正确理解了这个概念,myPoly应该是ADT,因为其中一个方法是纯虚函数(area方法),因为创建myPoly对象并不是我希望类的用户做的事情。myRectangle和myTriangle都派生自myPoly,而mySquare又派生自myRectangle。我还包括了我的测试计划,我计划在那里测试我的课程。我正在使用Code:

因此,我的目标是创建简单的shape类,这些类在适用的情况下可以相互继承。我有四个类:myPoly、myRectangle、myTriangle和mySquare。如果我正确理解了这个概念,myPoly应该是ADT,因为其中一个方法是纯虚函数(area方法),因为创建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 myPoly.cpp 我的矩形 myRectangle.cpp myTriangle.h myTriangle.cpp 迈斯夸尔 mySquare.cpp test.cpp
//实践继承、多态和抽象数据类型
//使用my shape类并尝试继承、多态性和ADT的主类
#包括“myRectangle.cpp”
//#包括“mySquare.cpp”
#包括“myTriangle.cpp”
#包括
int main()
{
myPoly*形状=新的myRectangle(20,20);
返回0;
}

我很好奇为什么我会出现这些错误,或者为什么我做的事情可能被认为是不好的/最佳实践,而不是仅仅接收一行代码来消除我的错误。

事实上,一切看起来都很好。这可能与链接程序时不包含myPoly.obj一样简单。我不熟悉Code::Blocks(虽然我知道它相当流行),但我假设如果您只是,例如,单击test.cpp并选择“Run”,Code::Blocks将尝试仅从一个源文件构建程序。您需要在您构建的每个程序中包含所有相关的源文件。

从代码的角度来看(至少在我看来),它看起来很不错,但是:

有两件事需要考虑:

  • 不要直接包含cpp文件。例如,在mySquare.h中,
    #include“myRectangle.cpp”
    应该是
    #include“myRectangle.h”
    。您希望包括头文件中提供的接口/声明,这些接口/声明告诉程序如何生成类,而不仅仅是函数定义

  • 其次,确保编译时使用了所有对象文件。我不知道代码块,但如果您使用的是g++或类似的东西,您可能希望对所有文件执行
    g++main.cpp myPoly.cpp mySquare.cpp等
    。例如,如果忘记myPoly.cpp,可能会发生类似的错误,因为它的函数没有定义


  • 你的警卫看起来很好。如果不是,则很可能会出现编译器错误,包括文件和行号信息。您发布的错误更像是链接器错误

    但是,您的代码有一个“问题”。一般来说,您应该只包含
    #h文件,而不包含.cpp文件


    现在来看看解决方案:我自己不熟悉代码::Blocks。不过,我希望我能提供一些基本信息,为您指明正确的方向。过去我用过的一些编译器允许我编译一个C++文件并运行这个程序。要编译一个包含多个文件的程序,我必须创建一个项目。(大多数现代编译器强制您从一开始就创建一个项目。)考虑到这一点,我建议您查看如何在Code::Blocks中为您的程序创建一个项目。

    此外,Other的人说:您没有正确地继承

    当你这样做的时候

    class Poly
    {
       Poly();
       ~Poly();
    }
    
    class Rect : public Poly()
    {
       Rect();
       ~Rect();
    }
    
    您需要按以下方式声明子构造函数:

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

    孩子必须在父亲完成构建后才能构建。

    快速扫描时,我注意到
    MySquare.h
    应该包含
    MyRectangle.h
    ,而不是
    MyRectangle.cpp
    谢谢您的关注。我会确保在我的代码中更改。好吧。。。否。如果不显式调用超类构造函数,则会自动调用默认构造函数。您的更改会增加混乱,并且根本不会更改生成的代码。实际上,如果您不显式地调用父构造函数,代码就会变得模棱两可。程序员很可能会忘记这样一个事实,即正在调用默认的父构造函数,某些事情可能会发生,也可能不会发生
    //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
    
    //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();
    }
    
    //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
    
    //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;
    }
    
    //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
    
    //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()
    {
    }
    
    //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;
    }
    
    class Poly
    {
       Poly();
       ~Poly();
    }
    
    class Rect : public Poly()
    {
       Rect();
       ~Rect();
    }
    
    Rect::Rect() : Poly()
    {
    
    }