1)面向对象
C语言使用面向过程的编程方式,而C++则增加了面向对象的编程方式。
面向过程:分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
面向对象 :把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。 性能对比:
优缺点:
1)面向对象易维护、易复用、易扩展。 因为面向对象有封装、继承、多态性的特性,所以可以设计出低耦合的系统,使系统更加灵活、更加易于维护。但是,面向对象性能比面向过程低。
2)面向过程性能比面向对象高。 因为类调用时需要实例化,开销比较大,比较消耗资源,所以当性能是最重要的考量因素的时候,比如单片机、嵌入式开发、Linux/Unix 等一般采用面向过程开发。但是,面向过程没有面向对象易维护、易复用、易扩展。
面向对象的三大特性:封装、继承、多态
2)类
类是一种将抽象(问题的本质)转换成用户自定义的类型的一种C++工具,它将数据表示和操纵数据的方法组合成了一个整洁的包。这个包提供对外的接口让用户调用。
类与结构的区别:类是C++对结构进行扩展后的结果。但结构的默认访问类型是public,而类为private。
1、类的声明
(继承相关的内容在之后会讨论)
#include
using namespace std;
class student//自己命名的类名
{
public://公共成员,也是一种公共接口,其内部的函数和数据可以被外部建立的对象直接调用
……
protected://保护成员,内部的函数和数据不可以被外部建立的对象直接调用,但可以被公有继承的类调用
……
private://私有成员,内部的函数和数据不可以被外部建立的对象直接调用
……
}
int main(){
{
student s;//类名 对象
}
关键字public和private和protect是类的控制访问,在类中的顺序没有固定要求,这三个分别描述了对类成员的不同的访问权限。但类中可以互相调用彼此,不受限制。
当没有使用任何的访问控制关键字时,默认算是private!
1、成员函数的说明
1、类中成员函数有三种定义方式
1)直接在类中定义
class student
{
public:
void function(int a,int b){//在类中直接建立函数,并调用私有成员里的变量
x=a;
y=b;
}
private:
int x,y;
}
2)在类声明中只给出成员函数的原型,成员函数的定义则放在类的外部
class student
{
public:
void function(int,int);//声明函数的返回类型(void),形参类型(int),函数名(function)
private:
int x,y;
}
void student::function(int a,int b)//::表示作用域,student::放在前面表示声明的函数属于student类
{
x=a;
y=b;
}
3)将函数作为内联函数进行处理
class student
{
public:
inline void function(int,int);//inline表示内联函数,声明函数的返回类型(void),形参类型(int),函数名(function)
private:
int x,y;
}
inline void student::function(int a,int b)//inline表示内联函数,::表示作用域,student::放在前面表示声明的函数属于student类
{
x=a;
y=b;
}
2、成员函数的使用
使用成员运算符调用成员函数
class print
{
public:
void _print(){
cout<<"你好!";
}
}
int main(){
print s;
s.print();
return 0;
}
输出:
你好!
构造函数的介绍:
当类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数,其作用是初始化对象的数据成员。
构造函数在类中不可缺少且函数名与类相同,构造函数不能有返回类型和返回值。
构造函数可以重载!(即下面几种构造函数可以共存)
构造函数建立在公有成员中,否则外部类对象无法调用构造函数来实现数据成员初始化!!!
构造函数的分类:
1)默认构造函数
如果你创建一个类时没有写任何构造函数,系统会自动生成默认的无参构造函数
class student
{
public:
/*
student(void){//系统自动创建的无参构造函数,但默认值可能不为0
x=0;
y=0;
}
*/
void function(int,int);//声明函数的返回类型(void),形参类型(int),函数名(function)
private:
int x,y;
}
2)初始化构造函数
class student
{
public:
student(int _x,int _y){//可以在类的对象建立的时候初始化对象内的数据的值
x=_x;
y=_y;
}
private:
int x,y;
}
int main(){
student s(5,6);//调用了构造函数,将5和6传递给了s对象里的x和y,使对象s内数据成员被初始化了
return 0;
}
3)复制(拷贝)构造函数
用于对象之间的值传递
默认拷贝构造函数
即没有定义构造函数,此时编译器会给我们自动产生一个拷贝构造函数,其作用是将另一个对象里的所有数据复制到该对象。
class student
{
public:
private:
int x,y;
}
int main(){
student s(5,6);
student c=s;//或者student c(s),作用相同,使用默认拷贝构造函数,将对象s当作参数传入c对象中,把s中所有数据传给对象c
}
自定义拷贝构造函数
可以自己定义要传送的数据
class student
{
public:
student(const student& c){//将对象c的x的值传给该类对象中的x,这里要传递的参数可以自己定义
x=c.x;
}
private:
int x,y;
}
int main(){
student s(5,6);
student c=s;//或者student c(s),作用相同,使用拷贝构造函数,将对象s当作参数传入c对象中,仅仅将s中的5传递给c中的x,没有全部传递(依据定义的拷贝构造函数)
}
4)类型转换构造函数
即实现类对象的数据类型的转换
只有一个参数
class student
{
public:
student(double c){//将对象c的x的数据类型变成double
x=c;
y=0;
}
private:
int x,y;
}
int main(){
student s=5.0;//调用了类型转换构造函数,将s.c的类型变成了double并赋值为5.0,c.y则为0
}
析构函数的介绍——
与构造函数相反,析构函数是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在生命周期结束时,C++编译系统会自动调用析构函数,来完成类的一些资源清理工作。
析构函数的特性——
1)析构函数名是在类名前加上字符~,且无返回类型,无参数,无返回值。
2)一个类有且只有一个析构函数。若用户没有显式定义,系统会自动生成默认的析构函数。
3)析构函数因为没有参数所以不能重载
class student
{
public:
student(int _x,int _y){//可以在类的对象建立的时候初始化对象内的数据的值
x=_x;
y=_y;
}
~student(){}//析构函数
private:
int x,y;
}
当我们使用string类时,经常会用到 string定义的两个对象直接相加,这是怎么办到的呢?
这就用到了类的运算符重载,即在类中定义一个该对象与其他对象的运算函数,最后返回该对象,实现两个类的运算。
双目运算符形参为另一对象,单目运算符则不必写形参名!
class student
{
public:
student operator +(const student&c){//student为返回类型,const student&c为参数,+为运算符,使用const表示只读,不能改变对象c内的数据
x=x+c.x;//this.x=this.x+c.x
y=y+c.y;//this.y=this.y+c.y
return *this;//返回this指针
}
private:
int x,y;
}
int main(){
student s(5,6);
student c=s;
c=c+s;//c.x=10,c.y=16
//另一种写法:c=operator+(c,s)
}
这里补充关于this指针的知识点:
在C++中,每个对象都能通过this指针来访问自己的地址。this指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。
class student
{
public:
/*student(int _x,int _y){//省略this指针写法
this.x=_x;
this.y=_y;
}*/
student(student *const this,int _x,int _y){//编译器眼中的函数
x=_x;
y=_y;
}
private:
int x,y;
}
关于const与函数的补充:
当const在函数名前面的时候修饰的是函数返回值,在函数名后面则表示是常成员函数,该函数不能修改对象内的任何成员,即只能发生读操纵,不能发生写操作!
1、为什么要使用友元函数?
类的封装性实现了数据隐藏,即类的私有成员在该类的作用域之外是不可见的。
但有时可能需要在类的外部访问类的私有成员,
为此 C++提供了一种允许类外的函数或其他的类访问该类的私有成员的方法,它通过关键字 friend 把其他类或函数声明为一个类的友元。
2、友元函数的定义与声明
友元函数是声明在类体内的一般函数,也可以是另一个类中的成员函数。友元函数并不是这个类中的函数,但它具有这个类中成员函数所具有的访问该类所有成员的功能。
1)使用普通函数作为友元函数
这样可以使用普通函数(已经定义的友元函数)在外部调用该类的数据成员。
语法:
friend 函数返回值类型 函数名(形式参数列表);
例子:
class student
{
public:
student(int _age, string _name, string _id) {
age = _age;
name = _name;
id = _id;
}
friend void function1(student &a) {//定义友元函数,作用:年龄+1,类型为student,即类名,使用&是为了传递可以改变的参数,作用类似指针
a.age++;
}
friend int function2(student &a,student &b){//定义友元函数,返回两个对象的年龄和
return a.age+b.age;
}
void print() {
cout << age << " " << name << " " << id;
}
private:
int age;
string name;
string id;
};
int main() {
student s1(23,"波哥","2017217293");
student s2(23,"徽哥","2017217292")
function1(s1);//23+1
int s=function2(s1,s2);//24+23
s.print();
}
从上例可以看出,
2)类的成员函数作为另一个类的友元函数
类中的成员函数作为另一个类的友元函数,其语法格式如下:
friend 类名::函数返回值类型 函数名(形式参数列表);
例子:
#include
using namespace std;
class B; //先声明B类,防止A类中调用function函数出错
class A //定义A类
{
public:
A(int _x)
{x=_x;}
void print()
{
cout << x <<endl;
}
void function(B &var);//定义A的一个成员函数,准备将其作为B的友元函数,所以形参类型为B类
private:
int x;
};
class B //定义 B 类
{
public:
B(int _y)
{y = _y;}
void print()
{
cout << y << endl;
}
friend void A::function(B &var){ //将 A 类中的成员函数 function() 声明为 B 类的友元函数,并定义函数功能
a = var.b;
}
private:
int y;
};
int main()
{
A m(2);
B y(3);
m.func(y); //A类对象m使用成员函数(友元函数)来访问B类成员函数
m.print();
return 0;
}
3、注意事项
在使用友元函数时,还需要注意以下几点: