‘PitchMatrix3D’不是‘Matrix3D’的成员——linux下编译碰撞检测包ColDet

来源:互联网 发布:非结构化数据如何分析 编辑:程序博客网 时间:2024/05/22 03:51

      ColDet是一个非常著名的开源碰撞检测包。我下载之后,使用包中自带的makefile.g++编译它,出现了一些bug:

g++ -c -O2 -DGCC coldet.cppIn file included from box.h:28:0,                 from coldetimpl.h:28,                 from coldet.cpp:25:math3d.h: 在成员函数‘void Matrix3D::rotate(const Vector3D&)’中:math3d.h:232:44: 错误: ‘PitchMatrix3D’在此作用域中尚未声明math3d.h:233:44: 错误: ‘YawMatrix3D’在此作用域中尚未声明math3d.h:234:44: 错误: ‘RollMatrix3D’在此作用域中尚未声明In file included from coldetimpl.h:28:0,                 from coldet.cpp:25:box.h: 在构造函数‘BoxTreeInnerNode::BoxTreeInnerNode(const Vector3D&, const Vector3D&, int)’中:box.h:150:38: 错误: ‘NULL’在此作用域中尚未声明box.h: 在成员函数‘virtual int BoxTreeInnerNode::getSonsNumber()’中:box.h:165:18: 错误: ‘NULL’在此作用域中尚未声明box.h:166:19: 错误: ‘NULL’在此作用域中尚未声明box.h: 在成员函数‘virtual BoxTreeNode* BoxTreeInnerNode::getSon(int)’中:box.h:177:12: 错误: ‘NULL’在此作用域中尚未声明box.h: 在成员函数‘virtual BoxTreeNode* BoxedTriangle::getSon(int)’中:box.h:193:43: 错误: ‘NULL’在此作用域中尚未声明box.h: 在成员函数‘virtual BoxedTriangle* BoxedTriangle::getTriangle(int)’中:box.h:198:12: 错误: ‘NULL’在此作用域中尚未声明coldet.cpp: 在成员函数‘virtual bool CollisionModel3DImpl::collision(CollisionModel3D*, int, int, float*)’中:coldet.cpp:51:33: 错误: ‘NULL’在此作用域中尚未声明coldet.cpp: 在成员函数‘virtual bool CollisionModel3DImpl::getCollidingTriangles(float*, float*, bool)’中:coldet.cpp:310:13: 错误: ‘NULL’在此作用域中尚未声明coldet.cpp:316:13: 错误: ‘NULL’在此作用域中尚未声明coldet.cpp:325:13: 错误: ‘NULL’在此作用域中尚未声明coldet.cpp:331:13: 错误: ‘NULL’在此作用域中尚未声明make: *** [coldet.o] 错误 1

      这个包历史比较悠久了,包中自带的readme.txt中给出的说明是用g++ 2.8编译。我的gcc版本已经是4.6.3了。奇怪,为什么2.8编译通过的代码,4.6.3竟然报错呢?

      根据错误提示,找到math3d.h中出现PitchMatrix3D的地方,一共有四处按照从上到下的顺序,第一处出现在struct Matrix3D中:

 friend Matrix3D PitchMatrix3D(const float theta);

第二处出现在struct Matrix3D的成员函数的定义中注意,这里就是第232行,出现关于PitchMatrix3D的错误)

inline voidMatrix3D::rotate(const Vector3D& v){   if (v.x!=0.0f) *this = PitchMatrix3D(v.x) * (*this);   if (v.y!=0.0f) *this = YawMatrix3D  (v.y) * (*this);   if (v.z!=0.0f) *this = RollMatrix3D (v.z) * (*this);}

第三处第四处就是真正的PitchMatrix3D函数定义了:

inline Matrix3DPitchMatrix3D(const float c, const float s){   return Matrix3D(1.0f, 0.0f, 0.0f, 0.0f,                   0.0f,    c,   -s, 0.0f,                   0.0f,    s,    c, 0.0f,                   0.0f, 0.0f, 0.0f, 1.0f);}inline Matrix3DPitchMatrix3D(const float theta){   return PitchMatrix3D((float) cos(theta), (float) sin(theta));}

      PitchMatrix3D在此作用域中尚未声明的错误让我纠结了很久。很显然,第三处和第四处就是PitchMatrix3D函数定义而已,没有错误。错就错在第二处。众目睽睽之下,struct Matrix3D的定义中明明写清楚了PitchMatrix3D是其友元函数,怎么到了第232行使用它的时候反而翻脸不认人了呢?难道结构体内声明友元函数,结构体外不能直接使用吗?

      说到结构体,很多习惯了c++中class的人们可能感觉别扭。好吧,其实在c++中,结构体和类的唯一区别就是,在默认情况下,类数据成员和成员函数的访问控制是private,结构体数据成员和成员函数的访问控制是public。这里为了方便,不妨就认为PitchMatrix3DclassMatrix3D的友元函数。在网上某些帖子的提示下,我找到圣经《C++编程语言》的11.5.1节:友元的查找。里面有句话,我摘抄如下:

像成员函数一样,一个友元声明不会给外围的作用域引进一个名字。......对于大型程序和大的类,一个类不能‘默不作声地’给它的外围作用域加入一些名字,维持这种性质是非常好的事情。

     茅塞顿开有木有啊亲!《C++编程语言》牛逼至尊啊亲!

     我以迅雷不及掩耳盗铃儿响叮当仁不让之势,在PitchMatrix3D作为友元函数出现之前,加上了PitchMatrix3D函数的声明。同样地,加上YawMatrix3D和RollMatrix3D的函数声明。再make,这个让人蛋疼的编译错误就灰飞烟灭了。

     当然,还有其他错误,就是提示一大堆“‘NULL’在此作用域中尚未声明”这个小意思,NULL不是关键字,需要提前定义的。在出错的文件前面加上#include <cstddef>即可。

      编译成功之后,得到的最终结果就是一个名为libcoldet.a的库文件。

原创粉丝点击