私は Stack Overflow が初めてで、C++ を独学していますが、まだかなりの初心者です。私が使用している本のかなりの部分を完成させた後 (時代遅れであると見なされたり、優れた本ではないと見なされる可能性があります)、必要な場合にのみ本を参照しながら、いくつかの概念を自分で試してみることで、いくつかの概念を強化することにしましたが、詰まっているように見えます。私が取り組んでいる概念は、継承、ポリモーフィズム、抽象データ型 (ADT)、およびクラスのコードをヘッダー ファイル (.h) と C++ ファイル (.cpp) に分離することです。テキストの壁については事前に申し訳ありませんが、私がどこにいる必要があるかを明確かつ具体的にしたいだけです.
したがって、私の目標は、必要に応じて相互に継承する単純な形状クラスを作成することです。myPoly、myRectangle、myTriangle、mySquare の 4 つのクラスがあります。この概念を正しく理解していれば、myPoly は ADT であるはずです。メソッドの 1 つが純粋な仮想関数 (area メソッド) であるためです。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 を自動的に含める方法があることを確認しました。誰かがそれについての洞察を提供できるなら、それは大歓迎です。また、包含ステートメントで引用符を使用することは、山括弧を使用することとどのように異なるかについても覚えています。以下は、私の小さなプロジェクト用に作成した 9 つのファイルすべてです。コメントのほとんどは、私にとってはちょっとしたメモやリマインダーです。
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;
}
なぜこれらのエラーが発生するのか、またはコード行を受け取ってエラーを解消するのではなく、なぜ私が行ったことが良い/ベスト プラクティスと見なされないのか、非常に興味があります。