2

我目前正在开发一个使用虚拟功能用户的程序。我只使用一个虚拟功能,并且遇到了一个常见的问题,我尝试了一个常见的解决方案,但不幸的是没有成功。

我最初有 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);
}

矩形.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 不应该是公开的

于 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

您的编译器至少需要一个翻译单元,其中在每个多态类的类定义之外定义了一个虚拟成员。只有存在这样的翻译单元,它才会实例化类的一些内部数据(虚函数表、多态类型信息)。

(免责声明:至少在很久以前我上次使用它时就是这种情况)

您可以为函数使用类外定义,BasicShape::calcArea也可以添加一个虚拟(甚至是纯虚拟)析构函数BasicShape并将其定义为类外。最好的地方可能是BasicShape.cpp文件。

顺便说一句:正如其他人所指出的,您通常不应将头文件作为单独的翻译单元传递给编译器。这不会有害(除了增加编译时间),但也没有好处。

于 2013-02-18T00:45:44.103 回答
0

好的,显然这一切似乎都是编译器问题。我一直使用 gedit 作为文本编辑器和 g++ 作为编译器,但是当我切换到代码块时,它工作得很好。

于 2013-02-24T02:51:47.337 回答