2

私は現在、仮想機能のユーザーを採用するプログラムに取り組んでいます。私は仮想関数を 1 つしか使用していませんが、私が試した一般的なソリューションで一般的な問題と思われるものに遭遇しましたが、残念ながら成功しませんでした。

私はもともと virtual void calcArea(); を持っていました。BasicShape.h では、純粋な仮想関数としての定義や指定はありません。私はそれを変更し、最後に {} を追加しました (同様の問題を持つ別のスレッドで提案されているように) が、それでも次のエラーが発生します:

私は入力します:

g++ BasicShape.h BasicShape.cpp circle.h circle.cpp Rectangle.h Rectangle.cpp driver.cpp -o Lab4

そして、私は得る:

/tmp/ccf1Y4Br.o: In function `BasicShape::BasicShape()': circle.cpp:(.text._ZN10BasicShapeC2Ev[_ZN10BasicShapeC5Ev]+0xf): undefined reference to `vtable for BasicShape'
/tmp/ccf1Y4Br.o:(.rodata._ZTI6circle[_ZTI6circle]+0x10): undefined reference to `typeinfo for BasicShape'
/tmp/ccc7gjtH.o:(.rodata._ZTI9Rectangle[_ZTI9Rectangle]+0x10): undefined reference to `typeinfo for BasicShape'
collect2: error: ld returned 1 exit status

何か案は?

これは実装ファイル BasicShape.h です。

#ifndef BASICSHAPE_H
#define BASICSHAPE_H

class BasicShape 
{
  protected: 
    double area;

  public:
    double getArea() const;
     virtual void calcArea();
};

#endif

付随する BasicShape.cpp ファイル:

#include "BasicShape.h"

double BasicShape::getArea() const
{
  return area;
}

void BasicShape::calcArea()
{
}

サークル.h:

#include "BasicShape.h"

#ifndef CIRCLE_H
#define CIRCLE_H

class circle : public BasicShape
{
  private:
    long centerX;
    long centerY;
    double radius;

  public:
    circle(long, long, double);
    long getCenterX() const;
    long getCenterY() const;
    virtual void calcArea();
};

#endif

サークル.cpp:

#include "circle.h"

// constructor
circle::circle(long userIn, long userIn2, double userIn3)
{
  centerX = userIn;
  centerY = userIn2;
  radius = userIn3;
  calcArea();
}

// accesors
long circle::getCenterX() const
{
  return centerX;
}

long circle::getCenterY() const
{
  return centerY;
}

// virtual function
void circle::calcArea()
{
  area = (3.14159 * radius * radius);
}

Rectangle.h

#include "BasicShape.h"

#ifndef RECTANGLE_H
#define RECTANGLE_H

class Rectangle : public BasicShape
{
  private:
    long width;
    long length;

  public:
    Rectangle(long, long);
    long getWidth() const;
    long getLength() const;
    virtual void calcArea();
};

#endif

長方形.cpp:

#include "Rectangle.h"

// constructor
Rectangle::Rectangle(long userIn, long userIn2)
{
  width = userIn;
  length = userIn2;
  calcArea();
}

// accessors
long Rectangle::getWidth() const
{
  return width;
}

long Rectangle::getLength() const
{
  return length;
}

void Rectangle::calcArea()
{
  area = (length * width);
}

ドライバープログラムは不完全ですが、とにかく私の問題とは無関係です (少なくとも私はそう思います)。

#include <cassert>
#include <iostream>
#include "BasicShape.h"
#include "Rectangle.h"
#include "circle.h"
using namespace std;

int main()
{

  cout << "Testing the functionality and efficiency of the circle class...\n";
  // declare circle object and test accessors and area computation
  circle objCircle(8,8,4);
  assert(objCircle.getCenterX() == 8);
  assert(objCircle.getCenterY() == 8);
  assert(objCircle.getArea() == 50.26544);
  cout << "Circle object testing completed successfully\n";

  cout << "Testing the functionality and efficiency of the Rectangle class...\n";
  // declare rectangle object and test accessors and area computation  
  //Rectangle objRec();

  return 0;
}
4

4 に答える 4

2

実際、指摘されたように、ヘッダーをコンパイルする必要はありません。(できますが、ここでは関係ありません --- gcc はプリコンパイル済みヘッダーを生成します)。

さらに興味深いのは、あなたの例は GCC 4.6.3 で完全に機能することです。

また、補足: calcArea は public であってはなりません

于 2013-02-18T00:35:21.927 に答える
1

ヘッダーをコンパイルしようとしないでください。

g++ BasicShape.cpp circle.cpp Rectangle.cpp driver.cpp -o Lab4

于 2013-02-18T00:20:27.013 に答える
1

コンパイラには、各ポリモーフィック クラスのクラス定義の外で仮想メンバーが定義されている翻訳単位が少なくとも 1 つ必要です。そのような翻訳単位がある場合にのみ、クラスの一部の内部データ (仮想関数テーブル、多態的な typeinfo) をインスタンス化します。

(免責事項: 少なくとも、私が最後に使用したときはそうでした)

関数のクラス外定義を使用するかBasicShape::calcArea、仮想 (場合によっては純粋仮想) デストラクタを追加してクラス外で定義することができますBasicShape。最良の場所はおそらくBasicShape.cppファイルでしょう。

ところで: 他の人が指摘したように、通常、ヘッダー ファイルを別の翻訳単位としてコンパイラに渡すべきではありません。これは (コンパイル時間が長くなる以外は) 害はありませんが、何の役にも立ちません。

于 2013-02-18T00:45:44.103 に答える
0

わかりました。どうやらこれはすべてコンパイラの問題のようです。この間ずっと、geditをテキストエディターとして使用し、g ++をコンパイラーとして使用していましたが、コードブロックに切り替えると、問題なく機能していました。

于 2013-02-24T02:51:47.337 に答える