面向对象中类是程序基本单元,分为
类内和类外数据共享和保护
1、类的静态成员
1.1、类静态成员概述
有时我们可能希望有某一个或几个数据成员为
同一个类的所有对象共有
,也就是实现数据共享
静态成员提供一种
同类对象
对数据的共享机制
静态成员分为:
–
静态数据成员
–
静态成员函数
静态数据成员是
类的属性
,这个属性不属于类的任何对象,但所有的对象都可以访问和使用它
如果将类的一个成员定义成静态型的,则该类的
所有对象的该成员共用同一存储空间。
1.2、静态数据成员的初始化
1.3、例子
每定义一个对象 执行一次构造函数;count++一次;
#include<iostream>
using namespace std;
class Student
{
public:
Student();
~Student();
void output();
int totalStu();
private:
int stuNum;
char name[20];
char sex[3];
static int count; //count为私有的,用于统计学生对象的人数
};
int Student::count=0;
Student::Student()
{
count++;
cout<<"请输入第"<<count<<"个学生的姓名:";
cin>>name;
cout<<"请输入学号:";
cin>>stuNum;
cout<<"请输入性别:";
cin>>sex;
}
Student::~Student()
{
cout<<"学生"<<count<<"析构!"<<endl;
count--;
}
void Student::output()
{
cout<<"姓名:"<<name<<endl;
cout<<"学号:"<<stuNum<<endl;
cout<<"性别:"<<sex<<endl;
}
int Student::totalStu()
{
return count;
}
int main()
{
Student a1,a2;
cout<<"当前的学生总人数为:"<<a1.totalStu()<<endl;
{
Student a3;
cout<<"第三个学生对象生成之后,";
cout<<"总人数为:"<<a1.totalStu()<<endl;
}
cout<<"当前的学生总人数为:"<<a2.totalStu()<<endl;
return 0;
}
1.4、LIO-SAM
可以看到在LIO-SAM中定义静态变量时在定义之初即进行了初始化;
并且ang_res_x代表角度分辨率;ringFlag代表雷达是否有线号;这两个变量的都只与使用的激光雷达有关;不随着类所创建的对象不同而改变
static float ang_res_x = 360.0/float(Horizon_SCAN);
static int ringFlag = 0;
2、 类的静态函数成员
2.1、概述
静态成员函数是类的一部分,而不是对象的一部分。如果要在类外调用公用的静态成员函数,要使用类名和域运算符”
::
”,其格式为:
类名::静态成员函数名(实参表);
对象名.静态成员函数名(实参表) ;
#include <iostream>
using namespace std;
class Student //定义Student类
{
int num;
int age;
float score;
static float sum; //静态数据成员
static int count; //静态数据成员
public:
Student(int n,int a,float s):num(n),age(a),score(s){ }
void total( );
static float average( ); //声明静态成员函数
};
void Student::total() //定义非静态成员函数
{
sum+=score; //计算总分
count++; //累统计总人数
}
float Student::average( ) //定义静态成员函数
{
return(sum/count);
}
float Student::sum=0; //对静态数据成员初始化
int Student::count=0; //对静态数据成员初始化
int main( )
{
Student stu[10]={ //定义对象数组并初始化
Student(10010,18,93),
Student(10020,19,68),
Student(10030,19,79),
};
int n;
cout<<"请输入学生个数(1--3):";
cin>>n; //输入需要求前面多少名学生的平均成绩
for(int i=0;i<n;i++)
{
stu[i].total( );
}
cout<<"前 "<< n<<" 位学生的平均成绩为 "<<Student::average( )<<endl;
return 0;
}
3、类的友元
C++为了进一步提高数据共享,通过友元机制实现
类外数据共享
。
友元不是该类的成员函数,但是可以访问该类的私有成员
。
• 对于一个类而言,它的友元是一种定义在该类外部的:
–
普通函数, 或者– 另一个类的成员函数, 或者– 另一个类,
但需要在该类体内进行说明。
3.1、友元函数
3.1.1、
非成员函数(普通函数) 作为友元函数
将一个函数声明为一个类的友元函数后,它不但可以通过对象名访问类的公有成员,
而且可以通过对象名访问类的私有成员和保护成员
访问对象中的成员
必须通过对象名
友元函数近似于普通的函数,它不带有this指针,
因此必须将对象名或对象的引用作为友元函数的参数,这样才能访问到对象的成员。
友元函数可以访问该类中的所有成员(公有的、私有的和保护的) ,
而一般函数只能访问类中的公有成员
#include <iostream>
using namespace std;
class A{
float x, y;
public:
A(float a, float b){x=a; y=b;}
float GetX(){return x;}
float GetY(){return y;}
float Sum(){ return x+y; } //成员函数
friend float Sum(A &a); //友元函数声明
} ;
float Sum(A &a) { return a.x + a.y; } //友元函数定义
float SumXY(A &a) //普通函数定义
{
return a.GetX()+a.GetY();
}
int main(){
A t1(4,5), t2(10,20), t3(100,200);
cout<<t1.Sum()<<endl; //成员函数的调用,利用对象名调用
cout<<Sum(t1)<<endl; //友元函数的调用,直接调用
cout<<SumXY(t1)<<endl; //调用一般函数
return 0;
}
3.2、友元类
当一个类作为另一个类的友元时,就意味着这个类的所有成员函数都是另一个类的友元函数
4、 数据的共享与保护
对于既需要共享、又需要防止改变的数据应该声明为
常量
4.1、常对象
常对象中
所有数据成员为常变量
,
必须要有初始值,且均不能被更新
常对象的数据成员是常数据成员,
但成员函数如不加const声明,编译系统将其作为非const成
员函数
常对象只能调用其常成员函数,
常成员函数是常对象唯一的对外接口
常成员函数可以访问常对象中的数据成员,
但不允许修改常对象中数据成员的值。
4.1.1 、常对象函数
#include<iostream>
using namespace std;
class Count{
public:
int add() const; //常成员函数的声明,是常对象的对外接口
void add1() const //常成员函数
{
cout<<" add1 "<<endl;
}
void add2() // 普通函数
{
cout<<"add2"<<endl;
}
};
int Count::add() const //常成员函数的实现
{
cout<<" add --"<<endl;
return 0;
}
int main()
{ const Count c1; //c1是常对象
c1.add(); //add()是const,则c1可以调用
c1.add1(); //add1()是const,则c1可以调用
c1.add2(); //错误,常对象不能调用普通成员函数
return 0;
}
4.2.2、常对象成员
4.3、常引用
#include "iostream"
using namespace std;
void Output( const int &i)
{
//i++; //错误,常量引用作为形参,其值不能被改变
cout<<i<<endl;
}
int main()
{
int i=12;
Output(i);
return 0;
}
4.3.1、A-LOAM
为了防止从雷达接受的点(pi)在输入转变的过程中被改变定义成常引用
//把某点的坐标从lidar坐标系转换到世界坐标系下。
void pointAssociateToMap(PointType const *const pi, PointType *const po)
{
Eigen::Vector3d point_curr(pi->x, pi->y, pi->z);
Eigen::Vector3d point_w = q_w_curr * point_curr + t_w_curr;
po->x = point_w.x();
po->y = point_w.y();
po->z = point_w.z();
po->intensity = pi->intensity;
//po->intensity = 1.0;
}