8 常见编译错:
1. 如果一个const对象访问一个非const成员函数会报错:C2662: “Example2<elemType>::print” : 不能将“this”指针从“const Example2<elemType>”转换为“Example2<elemType> &”
msdn的解释:Invoking a non-const member function on a const object.
4. 在函数定义之前调用函数引起的错误:
using namespace std;
cout << "begin at" << getTimeStr() << endl;
char * getTimeStr(){ return "2006/04/01" };
本想编译的错误是:函数未定义,但实际出现三个错误:
1. error C2365: “getTimeStr” : 重定义;以前的定义是“原先未知的标识符”
msdn解释为:'class member' : redefinition; previous definition was a 'class member'
比如:
class C1
{
int CFunc();
char *CFunc; // C2365, already exists as a member function
int CMem;
char *CMem(); // C2365, already exists as a member
};
这个编译错很是奇怪,怀疑是getTimeStr这个名字特殊,改为getTimeStr22后仍然如此。
2. error C2593: “operator <<”不明确
操作符'<<'在namespace std中定义了很多,由于函数getTimeStr的定义找不到,所以无法知道函数的返回值
这是overload函数引起的
3. error C3861: “getTimeStr22”: 即使使用参数相关的查找,也未找到标识符
这个才是真正的错误。
将getTimeStr()的定义移到前面就好了。不过error1还是没有搞清楚为何会出现。
6. template引起的编译错误非常难懂:
(1)如果使用模板类而没有include该类的头文件会出现下面错:
vector< int > _stack; //使用vector类
d:/len/begin3/iStack.h(31): error C2143: 语法错误 : 缺少“;”(在“<”的前面)
原因:编译器不知道vector标识符为一个模板的名字,所以引起后面的template parameter解析出错
解决办法:#include <vector> //将vector的头文件include进来
(2) template function引起的符号找不到link错:
场景:
//in common.h
template<class T> void myprint(T); //just declare in header
//in common.cpp //define in .cpp
#include "common.h"
template<class T> void myprint(T t){ cout << t <<endl; }
//in test.cpp
#include "common.h"
int main(){ myprint(100); return 0; }
link error: myprint<int>(int)找不到定义
原因:template compilation model有两种:inclusion model 和 separate model
VC 使用inclusion model,它要求template的定义在每个使用它的文件中都被include,一般将template的定义放在header中。
(separate model则像普通函数一样处理,将delare放在header中,然后在cpp中定义它,但千万注意:定义时要使用export关键字。)
解决办法:
1. 在common.cpp中定义myprint时加上export关键字,为:
export template<class T> void myprint(T){ cout << T <<endl; }
不过VC不支持export关键字,作罢。
2. 将定义放在common.h中:
//in common.h
template<class T> void myprint(T){ cout << T <<endl; }
正确运行,但是有潜在的错误:如果common.h被include两次,则会出现"myprint已定义“的编译错误
修正:
//in common.h
#ifndef common_h //可以用precompile指令#pragma once来代替这种技巧
#def common_h
template<class T> void myprint(T){ cout << T <<endl; }
#endif
(3)error C2664: “void std::sort<std::vector<_Ty>::iterator>(_RanIt,_RanIt)” : 不能将参数 2 从“std::vector<_Ty>::const_iterator (void) const”转换为“std::vector<_Ty>::iterator”
场景:
vector<string> line;
std::sort<Line::iterator>(line.begin(), line.end); //注意:函数调用end错误,应为end()
原因:调用参数的类型和 模板参数的类型不匹配
错误的函数调用end,使得:第一个调用参数类型为std::vector<_Ty>::iterator
第二个调用参数类型为std::vector<_Ty>::const_iterator (void) const (函数指针类型)
由错误的现象很难看到错误的原因。