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函数进行相应的定义。