2013-02-18 73 views
1

我目前正在使用虛擬功能的用戶程序。我只使用一個虛擬功能,並遇到了似乎是我嘗試過的一個常見解決方案的常見問題,但不幸的是沒有成功。未定義引用'typeinfo和'虛擬表

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

circle.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 

circle.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 

Rectangle.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; 
} 
+2

恕我直言,你應該先試着說明你的完整問題(包括錯誤信息,你期望的等),然後用大量代碼文件嚇跑人們。 – congusbongus 2013-02-18 00:29:26

+0

是的,它現在看起來有點威脅,現在我想到了它o_o thx的提示 – newwarrior21st 2013-02-18 00:31:54

回答

0

好吧,顯然這似乎都是編譯器問題。整個這段時間,我使用gedit作爲文本編輯器,使用g ++作爲編譯器,但是當我切換到代碼塊時,它工作得很好。

1

你不應該tryo編譯頭:

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

+0

我只是試圖編譯它,但我得到相同的錯誤 – newwarrior21st 2013-02-18 00:32:23

+0

,因爲你在構造函數中調用虛函數!!! 1 – billz 2013-02-18 00:37:01

+3

@billz:這不會導致鏈接錯誤。它有時會導致關於執行哪個函數的驚喜。 – aschepler 2013-02-18 00:44:23

2

事實上,正如有人指出,你有沒有編譯頭。 (儘管你可以,但這裏並不重要 - gcc會生成預編譯頭文件)。

更有趣的是:你的例子在這裏完美的工作,GCC 4.6.3。

此外,旁註:油杉不應該是公共

+0

所以你認爲這可能是g ++(我的編譯器)專有的問題? – newwarrior21st 2013-02-18 00:39:35

+0

@ newwarrior21st:我認爲你更可能意外地沒有提到代碼中的一些細微差別,或者你嘗試去編譯它。 (這些文件全都在同一個目錄下,全部保存等?) – aschepler 2013-02-18 00:42:55

+1

好吧,看起來你的編譯器不能在構造函數中處理虛函數(默認情況下這是壞事)。我建議修改你的代碼,如下所示:make area volatile,在BasicShape()中初始化爲-1;在所有嵌套的getArea()方法中,只需檢查區域是否根本不緩存(區域== -1),然後重新計算此值。類似'double circle :: getArea(){if(-1 == area)calcArea();返回區域; }' – MPogoda 2013-02-18 00:45:08

1

你的編譯器需要其中一個虛擬構件類定義之外定義爲每個多態類的至少一個翻譯單元。只有存在這樣的翻譯單元時,它纔會爲該類實例化一些內部數據(虛擬函數表,多態類型信息)。

(免責聲明:至少是這樣的話,當我最後一次使用它,很久以前)

您既可以使用外的類的定義爲BasicShape::calcArea功能或添加一個虛擬(可選甚至純虛)析構函數到BasicShape並將其定義爲超類。最好的地方可能是BasicShape.cpp文件。

順便說一句:正如其他人指出的,你通常不應該將頭文件作爲獨立的翻譯單元傳遞給編譯器。這不會損害(除了誇大你的編譯時間),但也是沒有好處的。

+0

你的意思是這樣的: 無效BasicShape ::油杉(){ } 當我這樣做,它給了我這樣的: BasicShape.cpp: 11:6:錯誤:'void BasicShape :: calcArea()'的原型不匹配'BasicShape'中的任何類型 BasicShape.h:14:20:error:candidate is:virtual double BasicShape :: calcArea() – newwarrior21st 2013-02-18 01:00:25

+0

是,就像你爲其他班級所做的那樣。只需將它放入'.cpp'文件中,而不是在類定義內部定義它。 – JoergB 2013-02-18 01:03:07

+0

它看起來很有幫助,但編譯器迴應如下: BasicShape.cpp:11:6:錯誤:'void BasicShape :: calcArea()'的原型不匹配'BasicShape'中的任何類型 BasicShape.h: 14:20:error:candidate is:virtual double BasicShape :: calcArea() – newwarrior21st 2013-02-18 01:06:52

相關問題