c++編譯報錯error LNK2001: 無法解析的外部符號
這個報錯是真的迷惑,一般會提示到無法解析的一個函數或者一個變量。
如果是變量的話,一般是靜態成員變量static typename xxx
沒有經過初始化便使用(不是類的數據成員的話vs會報錯)。
原因是我們如果只是聲明靜態變量而沒有初始化的話,編譯器是不會爲這個靜態變量分配空間的,只有當初始化靜態變量之後,編譯器纔會在內存的靜態區給這個變量分配空間,這樣程序才能在數據區找到這個變量並繼續使用。
如果是函數的話,我目前遇到的情況有:
1)只聲明瞭函數,但沒有完成定義;
2)今天遇到的,調用派生類的函數時,基類的同命虛函數沒有完成定義。
//Declaration.h
class myExc
{
protected:
double a;
double b;
public:
myExc() :logic_error(""){}
virtual void show();
};
class bad_gmean :myExc
{
public:
bad_gmean(){}
void show(){ cout << "gmean( " << a << " , " << b << " ): invalid arguments: a < 0 or b < 0\n"; }
};
class bad_hmean :myExc
{
public:
bad_hmean(){}
void show(){ cout << "hmean( " << a << " , " << b << " ): invalid arguments: a = -b\n"; }
};
上圖可以看到派生類重寫了基類的void show()
函數,但基類的void show()
並沒有進行內聯定義。
//main.cpp
/*
...
*/
catch (myExc &b)
{
b.show();
cout << "Exception type: " << typeid(b).name() << endl;
cout << "Try again.\n";
continue;
}
/*
...
*/
上圖可以看到主函數裏,我們通過基類引用的方式去調用派生類的show()
函數,雖然沒有直接使用基類的show()
,但是,使用基類引用的方式去調用派生類函數的方式屬於動態聯編,是在程序運行的時候的完成,而在程序的編譯階段,編譯器還是認爲這裏調用了基類的show()
函數,因此報錯。
修改方式很簡單,在確保不會調用到基類方法的前提下,可以直接內聯定義基類函數show()
:
virtual void show() {}
或者將函數聲明爲純虛函數,相應的基類也將變成抽象基類:
virtual void show() = 0;
如果要使用基類的show函數完成其他操作,則要對基類的show函數進行相應的定義。