赞
踩
前言:
作为一名机械专业学生,在没有C++基础的情况下,直接网上的代码资源学习ROS收获不大。虽然老师们并不要求我们会写相关代码,但能看懂代码段的含义是非常必要的,因此在正式开始ROS学习应用前需要对C++有基本概念。
一、C++介绍:
1.面向过程程序设计的缺点:
(1)可读性不佳:在面向过程的程序设计中,函数及其所操作的数据结构没有直观的联系,导致随着程序规模的增加可读性下降。
(2)扩展性差:面向过程程序设计没有“封装”和“隐藏”的概念,要访问某个数据结构中的某个变量可以直接访问,但要修改该变量时需要将所有访问该变量的语句都找出来修改,且难以差错和重用代码。
2.C++的特点:
C++是C语言的继承,既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。
二、类和对象:
1.介绍类和对象:
(1)面向对象编程:
面向对象是相对于面向过程来讲的,面向对象思想是把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模。
面向对象有三大特性:封装、继承和多态。
C++中的类是实现面向对象编程的核心要素。
(2)类的介绍:
类是根据客观事物抽象而成,形成一类事物;然后用类去定义对象,形成这类事物的具体个体;类把属性和方法进行封装,同时对类的属性和方法进行访问控制。
下面举例圆类说明:
1)代码段:
- //要使用C++输入输出工具,要提供这两行代码
- #include<iostream> //包含输入输出函数的头文件
- using namespace std; //释放std命名空间中的变量名,函数名以及类型名
-
- //声明常量PI=3.14
- const double PI=3.14;
-
- class Circle
- {
- public: //访问权限:公共的权限
-
- //属性
- double R;//半径
-
- //方法
-
- //获取圆的周长
- double cal_zc()
- {
- return 2*PI*R;
- }
-
- //获取圆的面积
- double cal_mj()
- {
- return PI*R*R;
- }
- };
-
- int main()
- {
- //创建对象
- Circle c; //声明类的对象
- c.R=10; //创建对象
- cout<<"半径为:"<<c.R<<endl; //访问公共成员属性半径并显示
- cout<<"周长为:"<<c.cal_zc()<<endl; //计算周长和面积并显示
- cout<<"面积为:"<<c.cal_mj()<<endl;
-
- return 0;
- }
2)结果:
3)解释代码:
①Circle是一个类,其中封装了一些方法:
一个属性:R
两个方法:cal_zc()和cal_mj(),分别计算圆的周长和面积
②public规定了类中的内容的访问权限。(访问权限有public,private和protected)
public:公有成员,可以在任何地方访问。
private:私有成员,只能在类内部访问。
protected:保护成员,可以在类内部或子类内部访问。
③main函数:
- int main()
- {
- //创建对象
- Circle c; //声明类的对象
- c.R=10; //创建对象
- cout<<"半径为:"<<c.R<<endl; //访问公共成员属性半径并显示
- cout<<"周长为:"<<c.cal_zc()<<endl; //计算周长和面积并显示
- cout<<"面积为:"<<c.cal_mj()<<endl;
-
- return 0;
- }
对象是根据类来创建的,声明类的对象就像声明基本类型的变量一样。
Circle类的公共成员可以直接被对象用''访问。
c.R访问了公共成员属性半径。
c.cal_zc和c.cal_mj访问了两个公共成员函数,分别计算了周长和面积。
(3)类包含的四个要素:
- classname
- {
- access specifiers//访问修饰符:public/private/protected
- date members/variables;//变量
- member fuctions(){}//方法
- };//分号结束一个类
1)类名classname
2)访问修饰符access specifiers
public:公有成员,可以在任何地方访问。
private:私有成员,只能在类内部访问。
protected:保护成员,可以在类内部或子类内部访问。
3)属性
4)方法
成员函数也可以类内声明,类外实现。注意,在类外实现时需要加上Circle::来指定作用域,表示实现的是Circle类中的成员函数。
- class Circle
- {
- public: //访问权限:公共的权限
-
- //属性
- double R;//半径
-
- //方法
-
- //获取圆的周长
- double cal_zc();
-
- //获取圆的面积
- double cal_mj();
-
- };
-
-
- double Circle::cal_zc()
- {
- return 2*PI*R;
- }
-
- double Circle::cal_mj()
- {
- return PI*R*R;
- }
(4)class与struct的区别:
class默认权限为私有private
struct默认权限为公共public
- struct A
- {
- int iNum;
- }
-
- class B
- {
- int iNum;
- }
-
- A a;
- a.iNum=2;//没有问题,struct默认权限为public
-
- B b;
- b.iNum=2;//编译出错,class默认权限为private
2.创建对象:
(1)对象的初始化和清理:
对象的初始化和清理是两个非常重要的安全问题。一个对象或者变量没有初始化状态,对其使用后果是未知的。使用完一个对象或变量,没有及时清理也会造成一定的安全问题。
C++利用构造函数和析构函数解决上述问题,这两个函数会被编译器自动调用。
(2)构造函数:
构造函数主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无需手动调用。
1)构造函数的结构:
- class Person
- {
- public:
-
- //有参构造函数
- Person(string name, int age)
- {
- this->name=name;
- this->age=age;
- }
- //this是一个指向当前类的指针
-
- //拷贝构造函数
- Person(const Person& p)
- {
- this->name=p.name;
- this->age=p.age;
- }
- //拷贝构造中传入的参数是以引用的方式传入,可节省空间
- //const是为了确保不改变传入的参数p
-
- public:
- string name;
- int age;
- };
该Person类中有两个属性name和age,利用函数重载机制编写了有参构造和拷贝构造两种构造函数,编译器会根据调用时参数的不同,自动选择正确的构造函数。在不提供构造函数时,编译器会自动提供一个默认的无参构造函数。
2)构造函数的调用方法:
- #include<iostream>
- #include<string>
- using namespace std;
-
- class Person
- {
- public:
- //有参构造函数
- Person(string name, int age)
- {
- this->name = name;
- this->age = age;
- }
-
- //拷贝构造函数
- Person(const Person& p)
- {
- this->name = p.name;
- this->age = p.age;
- }
-
- public:
- string name;
- int age;
- };
-
- void test01()
- {
- Person p1("Tom",10);//括号法
-
- Person p2 = Person("John",20);//显式构造法
-
- Person p3 = { "Harry",30 };//隐式构造法
-
- Person p4(p2);//拷贝构造
-
- cout << p1.name << " " << p1.age << endl;
- cout << p2.name << " " << p2.age << endl;
- cout << p3.name << " " << p3.age << endl;
- cout << p4.name << " " << p4.age << endl;
- }
- int main()
- {
- test01();
-
- return 0;
- }
有参构造函数有三个调用方法:括号法,显式法,隐式法。
拷贝构造则是在创建对象p4的时候直接传入一个已有的Person对象p2,利用p2的属性初始化p4。
(3)析构函数:
析构函数主要作用在于对象销毁前系统自动调用,执行一些清理工作。析构函数在对象消亡时自动调用。析构函数名与类名相同,前面加~,没有参数和返回值。
- #include<iostream>
- using namespace std;
-
- class Person
- {
- public:
-
- //有参构造函数
- Person(string name, int age)
- {
- this->name=name;
- this->age=age;
- cout<<"构造函数调用"<<endl;
- }
-
- //析构函数
- ~Person()
- {
- cout<<"析构函数调用"<<endl;
- }
-
- public:
- string name;
- int age;
- };
-
- void test02()
- {
- Person p1("James",30);
- cout<<p1.name<<" "<<p1.age<<endl;
- }
-
- int main()
- {
- test02();
- cout<<"1111"<<endl;
- return 0;
- }
运行结果显示了一个对象从创建到消亡的过程。在“析构函数调用”后打印输出“1111”,说明在执行完函数test02()时析构函数立即被调用,代表在函数中创建的对象被销毁。
3.静态成员:
(1)定义:
在成员变量和成员函数前加上关键字static称为静态成员。静态成员分为静态成员变量和静态成员函数。
1)静态成员变量:
所有对象共享同一份数据;在编译阶段分配内存;类内声明,类外初始化。
2)静态成员函数:
所有对象共享同一个函数;静态成员函数只能访问静态成员变量。
- class Runoob
- {
- public:
- static int runoob_age;//静态变量
- int runoob_users;//实例变量
-
- public:
- func
- {
- int runoob_local;//局部变量
- };
- };
(2)静态成员访问:
访问方式有两种:对象.或者类名::
- #include<iostream>
- using namespace std;
-
- class Person
- {
- public:
-
- static int count;//静态成员变量
- string name;
-
- };
-
- int Person::count=10;//类外初始化
-
- void test01()
- {
- Person p1;
- p1.name="Tom";
- cout<<"p1的名字:"<<p1.name<<", count:"<<p1.count<<endl;
- cout<<"p1的名字:"<<p1.name<<", count:"<<Person::count<<endl;
- }
-
- int main()
- {
- test01();
- return 0;
- }
count是Person类中的一个静态成员变量,可以用p1.count和Person::count两种方式来访问。而name是Person类中的一个普通成员变量,只能用p1.name的方式访问。
运行结果如下:
(3)示例:创建了两个对象,都对count属性进行了改变
- #include<iostream>
- using namespace std;
-
- class Person
- {
- public:
-
- static int count;//静态成员变量
- string name;
-
- };
-
- int Person::count=10;//类外初始化
-
- void test01()
- {
- Person p1;
- p1.count=0;
- cout<<"count:"<<Person::count<<endl;
- Person p2;
- p2.count=10;
- cout<<"count:"<<p1.count<<endl;
- }
-
- int main()
- {
- test01();
- return 0;
- }
运行结果如下:
运行结果说明Person类的所有对象共享同一个变量count。
4.访问权限:
(1)数据封装:
数据封装是面向对象编程的一个重要特点,它防止函数直接访问类的内部成员。类成员的访问限制是通过在类主体内部对各个区域标记public、private、protected来指定的。public、private、protected称为访问修饰符。
一个类可以有多个访问修饰符标记区域,类默认的访问修饰符是ptivate。
(2)访问修饰符:
1)public:公有成员,可以在任何地方访问。
2)private:私有成员,只能在类中或者友元函数中访问。
3)protected:保护成员,可以在类中的函数、子类函数及友元函数中访问。
分析示例:
- #include<iostream>
- using namespace std;
-
- class Person
- {
- //姓名,公共权限
- public:
- string m_Name;
-
- //汽车,保护权限
- protected:
- string m_Car;
-
- //银行卡密码,保护权限
- private:
- int m_Password;
-
- public:
- void func()
- {
- m_Name="张三";
- m_Car="拖拉机";
- m_Password=123456;
-
- cout<<m_Name<<endl;
- cout<<m_Car<<endl;
- cout<<m_Password<<endl;
- }
- };
-
- void test01()
- {
- Person p;
- p.func();
- cout<<p.m_Name<<endl;
- //cout<<p.m_Car<<endl;错误
- //cout<<p.m_Password<<endl;错误
- }
-
- int main()
- {
- test01();
- return 0;
- }
输出结果如下:
在这个例子中可以看出,func()作为成员函数可以访问私有成员变量和保护成员变量,然而在类外函数test01()中就不能访问m_Car和m_Password。
(3)友元:
类的友元函数是定义在类外部,但有权访问类的所有私有成员和保护成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
友元可以是一个函数(友元函数),也可以是一个类(友元类),在这种情况下,整个类及其所有成员都是友元。
示例:
- #include<iostream>
- using namespace std;
-
- class Box
- {
- double width;
- public:
- friend void printWidth(Box box);
- void setWidth(double wid);
- };
-
- //成员函数定义
- void Box::setWidth(double wid)
- {
- width=wid;
- }
-
- //请注意:printWidth()不是任何类的成员函数
- void printWidth(Box box)
- {
- /*因为printWidth()是Box的友元,它可以直接访问该类的任何成员*/
- cout<<"Width of box:"<<box.width<<endl;
- }
-
- //程序的主函数
- int main()
- {
- Box box;
-
- //使用成员函数设置宽度
- box.setWidth(10.0);
-
- //使用友元函数输出宽度
- printWidth(box);
-
- return 0;
- }
输出结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。