阅读 443

一篇文章入门C++

为什么要学习C++:

       抛开C++在一些物联网,高性能引擎(游戏等)及各种操作系统等行业使用的专业性,不论作为java开发还是其他开发,我们的知识体系里面必不可少的定有操作系统相关的知识,而关于操作系统,如果我们想要更深入的了解的话,看懂它的一些代码当然是必不可少的。再或者,开发一些高性能的工具或者组件,这些,都离不开C和C++,而对于C++的学习其实就基本上已经学会了C的一些东西(如果以前没有接触过C的话),基于二八法则,基本已够用。

C++语言的由来:

       1982年,美国AT&T公司贝尔实验室的Bjarne Stroustrup(本贾尼·斯特劳斯特卢普)博士在C语言的基础上引入并扩充了面向对象的概念,从而创造了C++这门程序语言,也叫做带类的C(c with class)。Bjarne Stroustrup(本贾尼·斯特劳斯特卢普)博士也被尊称为C++语言之父。

推荐c++学习开发工具

  windows上使用vc即可,mac上使用xcode即可
强烈推荐使用Qt creator 学习开发,也可以学习下Qt库

C++语法

认识C++的对象:

C++的函数和对象:

  • 注释方式(基本与java注释类似)
/*....*/  
//.... 
复制代码
  • 输入输出流

cin和cout是C++语言中进行输入输出操作的函数,定义在istream头文件中。
例子:

cout << "" << endl;  //c代表c系语言,out代表输出,endl代表换行 
复制代码
  • 使用命名空间 命名空间是C++语言中封装程序库名称的一种机制
    C++ 标准类库中的对象和函数都属于std命名空间,使用这些函数和对象时要using namespace std
    #include "iostream" //包含头文件
    #include "cmath"
    using namespace std
    复制代码
    • 使用std命名空间时注意:
      使用c语言中的头文件时,要写成“xxx.h”形式
      使用c++中的头文件则不能加上“.h”
命名空间可自定义,可嵌套,比如小王定义的是A命名空间,小李定义的是B命名空间,就算他们的函数重名了,一摸一样了也没事,可以通过命名空间::函数名来调用。
复制代码
  • 对象的定义及初始化
c语言:int x; x=0; 等价于 int x=0;  
c++ 语言(等价于上两条c语句):int x(0); 此种初始化语法在c++中称为构造函数语法
复制代码
  • 函数原型及其返回值
函数要有类型,若要得到处理结果则要使用return语句(与java类似,其实java的面世很多都是参考c++)。  
例子:
```
int result(int a,int b){
  int d;
  d = a+b;
  return d;
}
```  
函数调用在函数定义之前时要对函数进行声明  
例子:
```
int result(int a,int b); //进行函数声明
void main(){ //主函数
 ...
 z = result(x ,y); //调用定义的函数
 ...
}
int result(int a,int b){ //定义函数
 int d;
 d = a+b;
 return d;
}
```
复制代码
  • const修饰符和预处理程序

常量定义:(在c语言中是这样定义的,注意c++语法包含容纳c语法,c++就像是对c的一个扩充) #define PI 3.1415
(在c++中是这样定义的) 在变量定义之前加上const关键字,类似java,表示定义的变量值不可改变。 const int PI = 3.1415; (第一种)
const int PI(3.1415); (第二种,即构造函数语法)
利用const定义常量时必须给出常量的值,除非该常量是extern(外部变量、即全局变量)的。 以#开始,分为宏定义,文件包含和条件编译。

  • 程序的书写规则

注意缩进对齐,区分大小写,类似java,有所不同。

C++语言面向过程编程的特点

  • 函数重载
(与java类似)C++允许一个函数定义多个版本,使得一个函数完成多种功能,即同一个函数名定义多次。  
 例子: 
 ```
  int max(float a,float b){
   return a > b ? a:b;
  }
  
  int max(int a,int b,int c){
  int d;
  d = a > b ? a:b;
  return d > c ? d:c;
  }
  int max(int a,int b){
   return a>b ? a:b;
  }
 ```   
 
 如例子所示,重载函数的特点:  
 函数名相同,参数个数不同,或者参数类型不同。
 
 
复制代码
  • C++的数据类型(包括java等,几乎所有有语言的数据类型都囊括这些)
    1.void类型
    void表示空类型,或者无类型,表示函数无返回值。

    2.bool类型(逻辑型,布尔型)
    占1个字节,表示逻辑运算符中的 真 、假。

    3.整型(int、 long、 short)
    int、short至少16位
    long至少32位
    short不得比int长 int 不得比long长

    4.char型(字符型)
    占1个字节。

    5.实型(float/double/long double) 我们可以通过sizeof来观察这些数据类型的长度
    例子:

     cout << sizeof(bool) << endl;
     cout << sizeof(int) << endl;
     cout << sizeof(short) << endl;
     cout << sizeof(long) << endl;
     cout << sizeof(char)  << endl;
     cout << sizeof(float) << endl;
     ......
    复制代码

    6.&取地址符(取某一个变量的地址) 例子:

    int x;
    int *p;  //p是指针变量,指针变量能存放变量的地址
    p = &x; //&x表示取出变量x的地址,p = &x表示将变量x的地址取出后存入指针变量p
    复制代码

    7.常量表示
    整型: 0前缀表示8进制数,0x前缀表示16进制数,加L、I后缀表示长整型常量
    实型: F、f后缀表示浮点型常量(float);
    实数加L、I后缀表示long double类型;
    无前缀、无后缀的为double类型;

  • 动态分配内存

new动态分配内存  
一般格式: 指针变量 = new 类型\[size];  
new 运算符得到新分配空间的首地址、赋值给指针变量后,可根据指针变量的加减运算来使用这些空间。 
(与java不同,java有垃圾回收机制,自动释放内存,而c++是没有的)
delete 释放内存,使用完毕后要释放内存。  
delete p;
复制代码
  • 引用的使用方法
引用即使用变量的别名。  
定义形式:数据类型 & 别名 = 对象名;  
作用:别名与对象名对应同一个对象,共用同一段内存。对别名的修改会造成原对象的修改。  
例子:
```
int x;
int & a = x; //a是变量x的别名,a和x完全等价
```   
使用别名时的注意事项:  
1.不能定义引用的引用,如错误示范: ~~int & &r=x;~~  
2.不能直接定义数组的引用  

使用typedef定义某类型的别名   
一般格式:typedef 类型 类型别名  
例子:
```  
typedef long int lint; 
//long int i;
lint i; //lint i 等价于 long int i
```
复制代码
  • 对指针使用const限定符
1.左值和右值  
表达式:E1 = E2 ; E1是左值,是可被修改的;  
int *p,x = 1;
*p = 2;  &p表示指针p的地址  
2.指向常量的指针和常量指针  
const常量定义:表示const后的表达式不可改变,定义时必须给出表达式的值。  
例子:
```
int x = 11;
const int *p; //错误写法,必须初始化
const int *p = &x; //错误写法,*p是不能在=的左边
int * const p = &x; //正确写法(注意:p不可改变,但是*p可变)  
```    


3.指向常量的常量指针  
例子:
``` 
int x = 11;
const int * const p = &x; //表示p不可变,*p也是不可变的
```   
复制代码
  • 泛型算法应用于普通数组
泛型算法是C++标准模版库(Standard Template Library)提供的一组操作。利用这些操作可以简化数组操作。
要使用这些操作必须包含头文件\<algorithm>  
假定a,b是两个数组名,其长度为len 
例子: 
```  
reverse(a,a+len); //将数组a中的元素顺序反转(逆向),注意,len需要替换成长度,比如len=5,则len应该换成5
copy(a,a+len,b); //将a数组的内容原样复制给b数组 
reverse_copy(a,a+len,b); //将a数组的内容反转后复制给b数组  
sort(a,a+len) ;//将数组a中的元素按升序排序 
sort(a,a+len,greater<type>()) ;//将数组a中的元素按降序排序,type是数据类型,比如type是int,应该将type替换成int  
find(a,a+len,value);//在数组a中查找值为vavlue的元素,并返回位置指针  
copy(a,a+len,Ostream_iterator<type>(cout,"分隔字符串")); //Ostream_iterator表示输出流操作符,<type>表示要输出的数组类型,cout表示流输出操作,“分隔字符串”即就是分隔字符的
```
复制代码
  • 程序的编辑、翻译、运行
    程序从无到有为编辑,出来的c++源代码
    对比C和C++文件的各种后缀(由于历史原因,可谓花样真多,现在只展示统一的):

    语言头文件源文件
    c.h.c
    c++.h,但是openCV采用 .hppwindows平台 .cpp,linux平台 .cc
    源码进行编译为翻译
            c++的编译器有不少,其中熟知的有MSVC、GCC、Cygwin、MingW(Cygwin和MingW的英文发音),另外还有些 小众和新秀,像ICC(Intel C/C++ Compiler)、BCC(Borland C/C++ Compiler,快销声匿迹了)、RVCT (ARM的汇编/C/C++编译器,内置在ARM的IDE——RVDS中)、Pgi编译器……

    我们在linux下最常用的:
    GCC原名GNU C Compiler,后来逐渐支持更多的语言编译(C++、Fortran、Pascal、Objective-C、 Java、Ada、Go等),所以变成了GNU Compiler Collection(GNU编译器套装),是一套由GNU工程开发的支 持多种编程语言的编译器。GCC是自由软件发展过程中的著名例子,由自由软件基金会以GPL协议发布,是大多数类 Unix(如Linux、BSD、Mac OS X等)的标准编译器,而且适用于Windows(借助其他移植项目实现的,比如 MingW、Cygwin等)。GCC支持多种计算机体系芯片,如x86、ARM,并已移植到其他多种硬件平台.
    有时候,在linxu中下载一些第三方工具,提示我们需要下载相关gcc依赖等,就是因为这个工具由于c++开发,需要使用gcc进行编译才可执行使用。

执行即为c++编译后的文件,进行汇编和链接后的执行

从结构到类的演变:

结构的演化:

  • 结构发生质的演变
1.函数与数据共存  
c++允许结构中定义的函数,成为成员函数。在结构中同时定义成员变量和成员函数。  
使用格式:  
结构对象.成员变量   
结构对象.成员函数   
例子:  
``` 
#include <iostream>   //引入头文件 io
using namespace std; //使用c++标准类库中的类,需要使用std命名空间
struct point{ //point即为结构名,结构是c++中的一种数据结构,类似类
 double x,y;
 void updatexy(double a, double b){
  x = a;
  y = b;
 }
 
 void display(){
  cout << x << "\t" << y << endl; //endl是换行的意思
 } 
}; //注意结构数据定义完后要有分号

void main(){
 point p; //表示定义了p,与java不一样的是,这个p已经包含了java中= new .. 后面的动作,所以可直接调用p
 p.updatexy(1.5,1.7);
 p.display();
 cout << p.x << "\t" << p.y << endl;
}
```
复制代码

2.封装
如果定义结构体时,使用了private关键字,则产生封装性。 例子:

struct point{
 private: //这里区别于java,可以只写一个private,所有private的放在其下
  double x,y;  //这时候,在main中,通过point的变量名直接 . 变量,就不行了
 public:  //区别于java,可以只写一个public....
  void updatexy(double a,double b){
   x = a;
   y = b;
  }
  void display(){
  cout << a << "\t" << b << endl;
  }  
};
复制代码

在定义结构时,如果使用了private则产生封装性,表示成员为私有的,只能在结构体内部通过公有成员函数使用。如果未添加private,则表示默认为public。值得注意的是类在定义时默认却为private。

  • 使用构造函数初始化结构的对象

在定义结构时,与结构同名的函数称为构造函数。
如果定义的函数与某个已定义函数重名而参数类型或者个数不同,则称为函数重载。
例子:

struct point{
private:
  double x,y;
public:
  point(){};
  point(doube a,double b){
   x = a;
   y = b;
  }
  void updatexy(....){ ... } 
  .....
}
复制代码

与java的类类似,构造函数在定义结构体对象时自动执行,并根据是否初始化来自动选择所调用的构造函数。
这里需要区分的是:java的对象定义,在定义后,如果不new对象,它的变量名对应的对象则为null(这个null需要我们给赋给其),如果new对象的话,不仅会创建一个对象,还会自动进行初始化,也就是java的对象创建流程里面已经包含了初始化。但是c++则不一样,(c++也有new对象的方式,new出来的为动态对象)c++定义好后,就已经有这个对象了,但是初始化的过程由我们来控制,可以调用有参数的构造函数,那在对象定义完成后,也已经完成了初始化过程。

结构演化成一个简单的类:

将结构的struct替换为class即变为类的标准定义形式。 例子:

class point{
 private:
   double x,y;
 public:
   point(){};
   point(double a,double b){
   x = a;
   y = b;
   };  
   void updatexy(double a,double b){
   x = a;
   y = b;
   }
   void display(){
    cout << a << "\t" << b << endl;
   }   
};
复制代码

类图的表示(UML即统一建模语言等):

point
-x : double
-y : double
+point()
+updatexy()
其中,point为类名,x,y为类属性(成员变量),point和updatexy、display为类操作(成员函数)。

面向过程和面向对象:

直观的从一道题来区分:
给出两点坐标,计算亮点间距,并输出。
1.面向过程的求解步骤 :
步骤:
+ 输入x1,y1,x2,y2 四个数据
计算(x1,y1)和 (x2,y2)的距离
输出计算出的距离
2.面向对象的求解步骤
+ 设计类
将点设计为一个类,并提供相关的属性和操作
定义对象同时给出坐标
point A(x1,y1)
point B(x2,y2)
定义对象,然后获取坐标
计算距离并输出

C++面向对象程序设计特点

  • 对象

三要素:对象名,属性,操作

使用类和对象

  • 使用类和对象
    1.使用string对象
string
- str
+string()
+find()
该类是c++语言中的内部预定义类,要在程序中使用该类时必须添加头文件 #include <string> ;

**注意:**头文件引入的两种写法,#include <...> 和 #include "..." 。

类的初始化:string str1 = "A";
string str1("hello "); string str2 = "world";
与java类似,string对象允许使用 + 运算
* 使用complex对象
complex类用于定义一个复数对象,使用时添加头文件 #include <comlex>
定义格式:complex <int> num1(1,2);
* 使用对象总结
使用标准类库中的类时,必须添加头文件。
定义对象方式同变量定义方式类似。
定义对象时可对对象进行初始化。
同类的不同对象由对象属性来区分。
不同类的对象具有不同的成员函数可实现不同操作。
类是具有相同特征和操作的对象的抽象。

函数和函数模版

函数的参数及其传递方式

c语言中参数传递方式只有一种:值传递(值传递分为变量值传递和变量地址值传递)。
c++中分为:值传递和地址传递(引用传递),与java类似。 参数不同传递形式:对象作参数,对象指针作参数,对象引用作参数。
引用的声明形式:
数据类型 &别名 = 对象名; int x = 21;
int &a = x;
引用对象不是一个对立对象,与原对象同用一个地址空间,不占用内存。
对象的指针作参数时,指针变量中存放实参对象的地址。

函数的返回值

与java类似,但是多了指针类型。

内联函数

定义函数时,加inline关键字表示该函数为内联函数。
例子:

inline int wheatherNumber(char c){
 return c > '0' && c < '9' ? 1:0;
}
复制代码

程序中的内联函数在程序编译时,将函数替换至程序中函数调用位置,造成程序变长,效率提高。
注意事项: 内联函数中不能出现循环、switch语句等
内联函数一般短小,不宜过长
应在调用之前声明或定义

函数模版

有些函数重载时参数个数相同,只是类型不同,此时重载函数比较繁琐,可利用函数模版实现。
例子:

template <class type>  
type max(type a , type b){
  return a > b ? a:b;
}

void main(){
  int x = 1,y = 2;
  double x1 = 1.2,y = 2.1;
  
  int z;
  double z1;
  
  z = max(x,y);
  z1 = max(x1,y1);
  cout << "最大值:int类型为 " << z << "  dobule类型为  " << z1 <<endl;

}

复制代码

定义函数模版后,函数调用时根据函数参数类型来确定调用哪个版本的函数。函数执行时确定参数类型的函数称为模版函数。

类和对象

类及其实例化

  • 类的定义
例子模版:
```
class 类名{
 private:
   //私有的数据成员和成员函数
 public:
   //公有的数据成员和成员函数
 protected:
   //保护的数据成员和成员函数 
};

 void 类名::函数名(){
   
 }

```  
复制代码

:: 称为域限定符,表示函数是类的成员函数。在类外使用域限定符定义函数,若想定义为内联,加inline关键字就即可。
类内定义的函数默认为内联函数。

  • 使用类的对象
    类的对象的使用类似变量的使用。
    声明/定义对象,直接利用对象名使用,通过对对象的引用使用对象,通过指向对象的指针使用对象。
  • 数据封装
    与结构体封装类似

构造函数

  • 默认构造函数
    若类的定义中未定义构造函数,则c++编译器会自动产生一个不带参数的默认构造函数,类似于:point(){},此时不对对象进行初始化。若类中定义了构造函数,则不再产生默认构造函数。
  • 定义构造函数
    构造函数无返回值,这样可以减少编译器的工作,提高效率。
    构造函数与类同名。
    构造函数可以重载。
    构造函数系统自动调用。
  • 构造函数和运算符new
new 和构造函数一同起作用,即new首先给对象分配内存,然后自动调用构造函数来初始化这块内存。 
例子:  
```
void main(){
 
 Point *ptr = new Point;
 Point *ptr1 = new Point(1,2);
 delete ptr;
 delete ptr1; 
}
```  
复制代码

new建立的动态对象只能用delete删除,并会释放空间。

  • 复制构造函数
<类名>::<复制初始化构造函数>(const 类名 &引用名)
复制代码

析构函数

           析构函数的调用由编译器自动调用,析构函数名在类名前加~,析构函数无返回值,析构函数无参数,可以显示说明为void,析构函数不可以重载,析构函数在对象生命周期结束的时候由系统自动调用。

  • 定义析构函数
例子:  
 ``` 
 class Point{
  private:
         int x,y;
  public :
         Point(const Point&);
         Point(int a = 10,int b = 10);
         ~Point();
    
 }
    ……
 ```  
 类的对象组的每个元素调用一次构造函数,调用一次析构函数。  
 全局对象数组的析构函数在程序结束之前会被调用。 
 
复制代码
  • 析构函数和运算符delete
    delete后自动调用析构函数。与new 相反。
  • 默认析构函数
    编译器为没有析构函数的类自动产生一个空体析构函数,与构造函数类似。 分配几次内存调用几次构造函数,释放几次内存,调用几次析构函数。

this指针

       this指针是c++实现粉状的一种机制,它将对象和该对象调用的成员函数连接在一起。this指针保证了每个对象可以拥有自己的数据成员。(跟java类似) 例子:

Point::Point(int a=0,int b=0){
 this->x=a;
 this->y=b;
}
point::Point(const Point &p){
  this->x=p.x;
  this->y=p.y;
}
复制代码

类和对象的性质

  • 对象的性质
1.同一类的对象之间可以互相赋值; 
2.可以使用对象数组;
3.可以使用指向对象的指针;
4.对象可以用作函数参数; 
5.对象作为函数参数时,可以使用对象、对象引用和对象指针; 
6.一个对象可以用作另一个类的成员。
复制代码
  • 类的性质
1.使用类的权限 
2.不完全的类声明  
  只有当使用类产生的对象时,才进行内存分配。  
  类没有完全定义之前就引用该类。  
  不完全声明仅用于类和结构  
3.空类  
4.类作用域  
  类中默认控制权限是private  
复制代码

面向对象编程的文件规范

  • 编译指令
  • 在头文件中使用条件编译

#if ...

特殊函数和成员

静态成员

成员定义时使用static关键字
1.静态成员变量的初始化只能在类外进行。
2.类中的任何成员函数都可以访问静态成员变量。
3.访问静态成员时,一般加上类名限定。
4.静态成员变量是类的成员,不是对象的成 员。 5.对象未建立之前静态成员已经存在。
6.静态成员没有this指针,除非使用引用方式,否则不能存取类的成员。(与java类似,但是比java强大)
静态成员包括静态对象。

友元函数

可以实现两个类之间无限制的存取另一个类的成员。
友元函数可以访问私有成员,公有成员和保护成员。友元函数可以是一个类或函数。友元需要通过对象来使用类的成员。
友元的三种形式:
1.普通函数作为一个类的友元
例子:

  class Point{
  
     double x,y;
   public:
      Point(double x1,double y1){x = x1, y =y1}
      friend double max(Point & p1,Point & p2);
  };
  
  double max(Point &p1,Point &p2){  //注意,此函数为Point类的友元函数,与其成员函数有区别
    return p1.x+p1.y > p2.x+p2.y ? p1.x+p1.y : p2.x+p2.y; 
  }
复制代码

2.a类的成员函数作为b类的友元
例子:

 class A{
   private:
      int x;
   public:
      A(int a){x = a;}
      int getX(){return x;}
      void fun(B & t);
 };
 
 class B{
  private:
     int y;
  public:
     B(int b){y = b;}
     int getY(){return y;}
     friend void A::fun(B & t);
 };
 
 void A::fun(B & t){
   t.y = x;
 }
复制代码

3.a类作为b类的友元

  class B{
  
   private:
      int y;
   public:
      B(int b){y = b;}
      int getY(){return y;}
      friend class A;
  }
复制代码

const对象

const 可限定变量、指针、对象 函数、数据成员、成员函数。便是不可改变。
const对象只能调用const成员函数 例子:

 class circle{
   private:
     double r;
     const double PI;
     static int count;
   public:
     circle(double a):PI(3.14159265354){ //此即为const成员函数的定义方式
      r = a;
      count = count+1;
     }
 
 }
复制代码

main函数

main函数为入口函数,与java类似,但是只能有一个main

继承和派生

继承和派生的基本概念

继承关系是类与类之间的类属关系(从概念上来说,与Java类似,但是java只支持单一继承) 类的继承是指:派生类继承基类的所有数据成员和成员函数。用于表示类之间的类属关系,非构成关系。
派生类的特点:
1.增加新成员。
2.重定义已有成员函数。
3.改变基类的成员的访问权限。

单一继承

  • 一般形式
     class 派生类名:访问控制 基类名{
       private:
          成员列表;
       public:
          成员列表;       
       protected:
          成员列表;   
     }
    复制代码
  • 派生类的构造函数和析构函数
    派生类中继承的基类的成员初始化时,需要由派生类的构造函数调用基类的构造函数。 派生类的构造函数一般形式: 派生类名::派生类名(参数):基类名(参数){ //函数体 }
    构造函数和析构函数不能被继承。
  • 类的保护成员protected
    派生类使用基类的私有成员,保持封装性,可以将私有限定改为protected(与java类似)
  • 访问权限
  • 赋值兼容规则
  • isa和has-a的区别
    isa关系:继承和派生关系。
    has-a关系:一个类使用另一个类的对象作成员。
    公有继承关系一般和isa关系是等价的。
  • 公有继承存取权限表
基类派生类基类对象派生类对象
private不可访问不可访问不可访问
publicpublic可访问可访问
protectedprotected不可访问不可访问
  • 私有派生
定义派生时,用private限定 。基类的公有成员和保护成员变为私有成员。  
复制代码
  • 保护派生
定义派生时,用proetcted限定 。
降级使用,基类中的private变为不可访问,protect变为private,public变为protected。
复制代码

多重继承

一般形式(java只能单一继承,c++可以多重继承):
class 类1:访问控制 lei2,访问控制 类3{
private: //私有成员 protected: //保护成员 public: //公有成员
}

二义性及其支配原则

  • 作用域和成员名限定
    当派生类中从多个基类中继承得到同名函数时,在派生类中使用这些函数时,须使用类名限定!派生类的对象使用这些函数时,也需要进行类名限定!

  • 派生类支配基类的同名函数
    在基类和派生类有重名的成员时,优先派生类的成员,如果要访问基类成员,必须加上左右域符号 ::
    私有成员派生类不可访问,只有本类和友类可以访问
    如果派生类要访问基类的成员,基类成员应该用protected限定。

类模版与向量

类模版

  • 类模版的基础知识
    template<class T> class 类名{
     .....
    }
    复制代码
类模版的对象:类名<模版参数> 对象名(参数); 
模版类的成员函数定义形式: 
template<class T> 返回值类型 类名<T>::函数名(参数){
  //函数体
}
复制代码
  • 类模版的派生与继承
    模版类继承普通类,模版类作普通类的派生类。
    继承后成员使用与一般类的继承成员使用一样。
    模版类派生模版类。
    模版类使用时,须指出模版类参数。

向量与泛型算法

  • 定义向量列表
    向量是c++中一维数组的类版本,用于存放多个相同类型的数据。
    可以动态指定向量中元素的个数。可以使用泛型算法。(可类比java中的集合) 向量的声明形式:
    vector <类型> 向量名;
    vector <类型> 向量名(长度);
    vector <类型> 向量名(长度,a);
    vector <类型> 向量名1(向量名2);
    vector <类型> 向量名(a,a+长度);
    以上所说的a是数组名。

  • 向量的数据类型
    向量不仅可存取int,double等普通数据类型,也可以存储对象,指针,对象的指针。

  • 向量的基本操作方法
    类比数组,以及使用泛型算法。

多态性和虚函数

多态性

  • 赋值兼容规则是指在需要基类对象的du任何地方都可以使用zhi公有派生类的对象来替代。通过公有dao继承,派生类得到了基类中除构造函数、析构函数之外的所有成员,而且所有成员的访问控制属性也和基类完全相同。这样,公有派生类实际就具备了基类的所有功能,凡是基类能解决的问题,公有派生类都可以解决。赋值兼容规则中所指的替代包括以下的情况:

   1.派生类的对象可以赋值给基类对象。

   2.派生类的对象可以初始化基类的引用。

   3.派生类对象的地址可以赋给指向基类的指针。

  • 静态联编中的赋值兼容性和名字支配规律。
    类的对象和调用的函数一一对应,程序编译时即可确定对象调用哪个函数,称为静态联编。

通过指针调用成员函数时:所调用成员函数为指针所属类的成员函数,即有赋值兼容规则决定指针调用的成员函数

  • 动态联编的多态性
要实现程序运行时决定指针所调用的函数是基类的还是派生类的,即:动态联编。可以利用虚函数实现动态联编。
复制代码

虚函数

  • 虚函数的格式:
virtual double area(){
 return 0;
}
虚函数不能是静态成员。
复制代码
  • 虚函数实现多态性
    使用虚函数实现多态的三个前提:
    1.类之间的继承关系满足赋值兼容性规则;
    2.改写了同名虚函数; 3.根据赋值兼容性规则使用指针(或引用)。

  • 构造函数和析构函数调用虚函数
    标准c++不支持虚构造函数 ,支持虚析构函数。

  • 纯虚函数与抽象类
    1.纯虚函数的格式
    class 类名{ virtual 函数类型 函数名(参数列表)=0; }
    2.抽象类
    包含纯虚函数的类称为抽象类
    抽象类的派生类如果没有实现抽象类中的全部纯虚函数,这个派生类依旧是抽象类。
    纯虚函数与空的虚函数是不同的:
    1.virtual void area()=0; //纯 2.virtual vodi area(){} //空

多重继承与虚函数

首先,多重继承是多个单一继承的集合。

类成员函数的指针与多态性

在派生类中,当一个指向基类成员函数的指针指向一个虚函数,并且通过指向对象的基类指针(或引用)访问这个虚函数时,会发生多态性。

运算符重载和流类库

运算符重载

  • 重载对象的赋值运算符

  • 运算符重载的实现

  • << >> 和 ++ 运算符重载的实例
    例子:

      //插入符函数的一般形式
     ostream &operator<<(ostream& output,类名& 对象名){
        return output;
     }
    复制代码
  • 类运算符和友元运算符的区别

  • 下标运算符 “[ ]”的重载

流类库

  • 流类库的基础类
    把接收输出数据的地方叫做 目标
    把输入数据来自的地方叫做 源头