标签:
在写代码的时候,中间遇到了一些问题,后来查阅了一些书籍,并且在网上找了一些相关知识,以下遇到的问题和解决方案。
刚开始写的时候,代码打算按照头文件和源文件分开的形式来写,但是来回使用#include就会造成类成员函数的重载定义。
如果a.h中含有类A的定义,b.h中含有类B的定 义,由于类B的定义依赖了类A,所以b.h中也#include了a.h。现在有一个源文件,它同时用到了类A和类B,于是程序员在这个源文件中既把 a.h包含进来了,也把b.h包含进来了。这时,问题就来了:类A的定义在这个源文件中出现了两次!于是整个程序就不能通过编译了。
使用"#define"配合条件编译可以很好地解决这个问题。在一 个头文件中,通过#define定义一个名字,并且通过条件编译#ifndef...#endif使得编译器可以根据这个名字是否被定义,再决定要不要继 续编译该头文中后续的内容。
故在每个头文件的开头均有:
#ifndef A #define A //XX.h #endif
另外,在Frame,Robot等类中数据成员含有其他类的对象,这样在定义构造函数时,要初始化对象,同时也要定义拷贝构造函数,这样才能定义返回该类对象的函数。
因为在函数的调用过程中,要用到类的拷贝构造函数。
如下:
Box f() { Box box1(12,15,18); return box1; } int main() { Box box2; box2=f(); }
由于box1是在函数f中定义的,在调用f函数结束后,box1的生命周期就结束了,因此并不是将box1带回main函数,而是在函数f结束前执行return 语句时,调用Box类中的复制构造函数,按照box1复制一个新的对象,然后将它赋值给box2。
例如在Slover.h文件中,声明了两个Solver类的成员函数
JointFrame ToJoint(Point &);
Point JointTo(JointFrame &);
这样,在函数返回的时候要调用复制构造函数,若Point和JointFrame类中有对象的话,就需要自己定义拷贝构造函数,而不能使用默认的拷贝构造函数。
如下是一段程序来表示如何来定义类的构造函数和拷贝构造函数:
#include<iostream> #include<cmath> using namespace std; class Point { public : Point(int xx=0,int yy=0){X=xx;Y=yy;} Point(Point &p); int GetX() {return X;} int GetY() {return Y;} private: int X,Y; }; Point::Point(Point &p) //拷贝函数的实现 { X=p.X; Y=p.Y; cout<<"Point拷贝函数被调用"<<endl; } //类的组合 class Line { public: Line(Point xp1,Point xp2); Line(Line &); double GetLen(){return len;} private: Point p1,p2; double len; }; //组合类的构造函数 Line::Line(Point xp1,Point xp2) :p1(xp1),p2(xp2) { cout<<"Line构造函数被调用"<<endl; double x=double(p1.GetX()-p2.GetX()); double y=double(p1.GetX()-p2.GetY()); len=sqrt(x*x+y*y); } //组合类的拷贝构造函数 Line::Line(Line &L):p1(L.p1),p2(L.p2) { cout<<"Line 拷贝构造函数被调用"<<endl; len=L.len; } //主函数 int main() { Point myp1(1,1),myp2(4,5); //建立Point类的对象 Line line(myp1,myp2); //建立Line类的对象 Line line2(line); //利用拷贝构造函数建立一个新对象 cout<<"The length of the line is :"; cout<<line.GetLen()<<endl; cout<<"The length of the line2 is :"; cout<<line2.GetLen()<<endl;
另外,由于使用Eigen,所以在进行计算时,可以充分利用其函数:
// Vector2d a(5.0, 6.0); // Matrix2d m; m << 1, 2, 3, 4, 5, 6;
Eigen提供+、-、一元操作符“-”、+=、-=,例如:
二元操作符+/-表示两矩阵相加(矩阵中对应元素相加/减,返回一个临时矩阵): B+C 或 B-C;
一元操作符-表示对矩阵取负(矩阵中对应元素取负,返回一个临时矩阵): -C;
组合操作法+=或者-=表示(对应每隔元素都做相应操作):A += B 或者 A-=B
另外,矩阵还提供与标量(单一个数字)的乘除操作,表示每个元素都与该标量进行乘除操作。例如:
二元操作符*在:A*a中表示矩阵A中的每隔元素都与数字a相乘,结果放在一个临时矩阵中,矩阵的值不会改变。
对于a*A、A/a、A*=a、A /=a也是一样,例如下面的代码:
#include <iostream> #include <Eigen/Dense> using namespace Eigen; int main() { Matrix2d a; a << 1, 2, 3, 4; Vector3d v(1,2,3); std::cout << "a * 2.5 =\n" << a * 2.5 << std::endl; std::cout << "0.1 * v =\n" << 0.1 * v << std::endl; std::cout << "Doing v *= 2;" << std::endl; v *= 2; std::cout << "Now v =\n" << v << std::endl; }
矩阵的相乘,矩阵与向量的相乘也是使用操作符*,共有*和*=两种操作符,其用法可以参考如下代码:
#include <iostream> #include <Eigen/Dense> using namespace Eigen; int main() { Matrix2d mat; mat << 1, 2, 3, 4; Vector2d u(-1,1), v(2,0); std::cout << "Here is mat*mat:\n" << mat*mat << std::endl; std::cout << "Here is mat*u:\n" << mat*u << std::endl; std::cout << "Here is u^T*mat:\n" << u.transpose()*mat << std::endl; std::cout << "Here is u^T*v:\n" << u.transpose()*v << std::endl; std::cout << "Here is u*v^T:\n" << u*v.transpose() << std::endl; std::cout << "Let‘s multiply mat by itself" << std::endl; mat = mat*mat; std::cout << "Now mat is mat:\n" << mat << std::endl; }
因此,可以利用:
Vector m ;
m.transpose()*m;
这样便可求得向量模的平方,但是在对向量单位化的时候,不能使用:
m /= sqrt(m.transpose()*m);
这是因为:
//If you want to replace a matrix by its own transpose, do NOT do this: m = m.transpose(); // bug!!! caused by aliasing effect //Instead, use the transposeInPlace() method: m.transposeInPlace(); //which gives Eigen good opportunities for optimization, or alternatively you can also do: m = m.transpose().eval();
标签:
原文地址:http://www.cnblogs.com/zhibos/p/5118200.html