我在测试书上的例子时,按书上把类的构造器前加了inline,main函数和类的实现不在同一个文件中,在测试时报了如下错误:
1>Main.obj : error LNK2019: 无法解析的外部符号 "public: __thiscall UserProfile::UserProfile(void)" (??0UserProfile@@QAE@XZ),该符号在函数 _main 中被引用
1>Main.obj : error LNK2019: 无法解析的外部符号 "public: __thiscall UserProfile::UserProfile(class std::basic_string,class std::allocator >,enum UserProfile::uLevel)" (??0UserProfile@@QAE@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@W4uLevel@0@@Z),该符号在函数 _main 中被引用
1>D:\Visual Studio 2015\Projects\STLStudy\Debug\STLStudy.exe : fatal error LNK1120: 2 个无法解析的外部命令
我把inline去掉或是把main函数放在类的实现的文件中时,就可以正常运行了。想知道为什么。编译器是vs2015
贴出你的代码看下。关键看你的include怎么使用,类怎么定义的。
这是Essential C++上的一个例子,下面是代码
main.cpp
#include"UserProfile.h"
#include
using namespace std;
extern ostream& operator<<(ostream &os, const UserProfile &rhs);
extern istream& operator>>(istream &is, UserProfile &rhs);
int main() {
UserProfile anon;
cout << anon;
UserProfile anon_2;
cout << anon_2;
UserProfile anna("Annal", UserProfile::Guru);
cout << anna;
anna.bump_guess_count(27);
anna.bump_guess_correct(25);
anna.bump_login_count();
cout << anna;
cin >> anon;
cout << anon;
return 0;
}
UserProfile.h
#pragma once
#include
#include
using namespace std;
class UserProfile
{
public:
enum uLevel
{
Beginner,Intermediate,Advanced,Guru
};
UserProfile();
UserProfile(string login,uLevel = Beginner);
~UserProfile();
bool operator==(const UserProfile&);
bool operator!=(const UserProfile &rhs);
//following functions are used to read data
string login()const {
return _login;
}
string user_name()const {
return _user_name;
}
int login_count()const {
return _times_logged;
}
int guess_count()const {
return _guesses;
}
int guess_correct()const {
return _correct_guesses;
}
double guess_average()const;
string level()const;
//following functions are used to write data
void reset_login(const string &val) {
_login = val;
}
void user_name(const string &val) {
_user_name = val;
}
void reset_level(const string&);
void reset_level(uLevel newlevel) {
_user_level = newlevel;
}
void reset_login_count(int val) {
_times_logged = val;
}
void reset_guess_count(int val) {
_guesses = val;
}
void reset_guess_correct(int val) {
_correct_guesses = val;
}
void bump_login_count(int cnt = 1) {
_times_logged += cnt;
}
void bump_guess_count(int cnt = 1) {
_guesses += cnt;
}
void bump_guess_correct(int cnt = 1) {
_correct_guesses += cnt;
}
private:
string _login;
string _user_name;
int _times_logged;
int _guesses;
int _correct_guesses;
uLevel _user_level;
static map<string, uLevel> _level_map;
static void init_level_map();
};
UserProfile.cpp
#include"UserProfile.h"
#include
inline UserProfile::UserProfile()
:_login("guest"), _user_level(Beginner),
_times_logged(1), _guesses(0), _correct_guesses(0)
{
static int id = 0;
char buffer[16];
_itoa(id++, buffer, 10);
_login += buffer;
}
inline UserProfile::UserProfile(string login, uLevel level)
:_login(login),_user_level(level),
_times_logged(1),_guesses(0),_correct_guesses(0)
{
}
UserProfile::~UserProfile()
{
}
inline double UserProfile::guess_average() const
{
return _guesses
? double(_correct_guesses) / double(_guesses) * 100
: 0.0;
}
inline bool UserProfile::operator==(const UserProfile &rhs) {
if (_login == rhs._login && _user_name == rhs._user_name) {
return true;
}
return false;
}
inline bool UserProfile::operator!=(const UserProfile &rhs) {
return !(*this == rhs);
}
inline string UserProfile::level()const {
static string _level_table[] = { "Beginner","Intermediate","Advanced","Guru" };
return _level_table[_user_level];
}
ostream& operator<<(ostream &os, const UserProfile &rhs) {
os << rhs.login() << ' '
<< rhs.level() << ' '
<< rhs.login_count() << ' '
<< rhs.guess_count() << ' '
<< rhs.guess_correct() << ' '
<< rhs.guess_average() << endl;
return os;
}
map UserProfile::_level_map;
void UserProfile::init_level_map()
{
_level_map["Beginner"] = Beginner;
_level_map["Intermediate"] = Intermediate;
_level_map["Advanced"] = Advanced;
_level_map["Guru"] = Guru;
}
inline void UserProfile::reset_level(const string &level)
{
map::iterator it;
if (_level_map.empty()) {
init_level_map();
}
_user_level =
((it = _level_map.find(level)) != _level_map.end())
? it->second : Beginner;
}
istream& operator>>(istream &is, UserProfile &rhs) {
string login, level;
is >> login >> level;
int lcount, gcount, gcorrect;
is >> lcount >> gcount >> gcorrect;
rhs.reset_login(login);
rhs.reset_level(level);
rhs.reset_login_count(lcount);
rhs.reset_guess_count(gcount);
rhs.reset_guess_correct(gcorrect);
return is;
}