使用#include和Inclusion保护的独立文件中的C++继承

xmd2e60i  于 2022-12-24  发布在  其他
关注(0)|答案(4)|浏览(141)

我是堆栈溢出的新手,正在自学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()'

我得到了42个类似的错误,都是关于myPoly类的方法。当我试图为myRectangle和myTriangle构建.cpp文件时,也会发生这种情况。通过对我在这个小项目中遇到的问题进行研究,我觉得我的包含保护或#include语句出了问题。有些东西没有被正确地包含或者被包含太多次了。一开始我把myPoly的.cpp文件提供给myRectangle和myTriangle,但在一些地方读到,包括myPoly的.h文件更有效,以及一些如何自动包括其. cpp。如果有人能提供一些见解,非常感谢。2我还记得在包含语句中使用引号和使用尖括号有什么不同。3下面是我为我的小项目制作的九个文件。大多数评论对我来说都是小纸条或提醒。

我的聚合物. 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

我的聚合物. 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;
}

我的广场. 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

我的广场. 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;
}

我非常好奇为什么我会得到这些错误,或者为什么我所做的事情可能不被认为是好的/最佳实践,而不是仅仅接收一行代码来使我的错误消失。

0sgqnhkj

0sgqnhkj1#

你的包含保护看起来很好。如果它们不好,你很可能会得到一个编译器错误,包括文件和行号信息。你发布的错误看起来更像是一个链接器错误。
但是,您的代码有一个“问题”,一般来说,您应该只使用#include .h文件,而不是.cpp文件。
现在来看看解决方案:我自己对Code::Blocks并不熟悉。但是,我希望我能给予一些一般性的信息,为您指明正确的方向。我过去使用的一些编译器默认允许我编译单个C++文件并运行程序。要编译包含多个文件的程序,我必须创建一个项目。(大多数现代编译器强制您从一开始就创建一个项目。)记住这一点,我建议您查看如何在Code::Blocks中为您的程序创建一个项目。

bvn4nwqk

bvn4nwqk2#

从代码的Angular 来看(至少从我的Angular 来看),它看起来相当不错,但是:

有两件事需要考虑:

1.不要直接包含cpp文件。例如,在mySquare.h中,#include "myRectangle.cpp"应该是#include "myRectangle.h"。您希望包含头文件中提供的接口/声明,这些声明告诉程序如何生成类,而不仅仅是函数定义。
1.第二,确保你编译的是所有的目标文件,我不知道代码块,但是如果你使用g++或者类似的东西,你会希望对所有文件执行g++ main.cpp myPoly.cpp mySquare.cpp etc.,如果你忘记了myPoly.cpp,可能会发生这样的错误,因为它的函数没有定义。

x7rlezfr

x7rlezfr3#

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

k4emjkb1

k4emjkb14#

除了那些人说的:你没有继承权...
当你这样做

class Poly
{
   Poly();
   ~Poly();
}

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

需要按以下方式声明子级的构造函数:

Rect::Rect() : Poly()
{

}

子进程必须在父进程完成构造之后才能构造。

相关问题