C++语法课入门 慕课网笔记

https://www.imooc.com/u/1349694/courses?sort=publish

C++远征之模板篇
C++远征之多态篇
C++远征之多态篇
C++远征之继承篇
C++远征之封装篇(上)
C++远征之封装篇(上)
C++远征之离港篇
C++远征之起航篇

C++
应用:嵌入式 游戏 网络 系统
特点:快 节省资源

与C的关系
范围:c是++的子集
特性:c面向过程 C++ 面向对象、面向过程

IDE:Xcode

数据类型
C的类型
基本类型
整型 int
字符型 char
浮点型
单精度 float
双精度 double
构造类型
数组
结构体 struct
枚举 enum
联合体 union
指针类型
空类型 void

C++的新类型 bool

初始化方法
C的初始化
int x = 1024
C++的初始化
int x = 1024
int x(1024)
随用随定义
C的定义 :定义在函数体的最前面
C++的定义:什么时候用 什么时候定义

输入与输出 I/O
C的输入输出
输入:输入设备-输入流-scanf-变量
输出:变量-printf-输出流-输出设备
C++的输入输出
输入:输入设备-输入流-cin-变量
输出:变量-cout-输出流-输出设备

输出语法形式cout:
//不需要写变量的类型 endl 相当于换行符回车
cout<< x << endl;
// << endl 可以忽略
cout<<“x+y=”<<x+y<<endl;
输入语法形式cin:
//外界磁盘中数据赋值到x变量中
cin >>x;
cin >>x>>y;

好处:不用关心占位符。不用关心数据类型 不容易出现问题

eg1:

#include <iostream>
#include <stdlib.h>
using namespace std;
//要求:提示用户输入一个整数,将该整数分别以8进制,10进制,16进制打印在屏幕上
//要求:提示用户输入一个布尔值(0或1),以布尔方式将值打在屏幕上
int main(int argc, const char * argv[]) {
    // insert code here...
    cout << "请输入一个整数" << endl;
    int x = 0;
    cin >> x;
    cout<<oct<< x <<endl;//8进制 英文缩写
    cout<<dec<< x <<endl;//10进制
    cout<<hex<< x <<endl;//16进制
    cout << "请输入一个布尔值(0或1)" << endl;
    bool y = false;
    cin >>y;
    cout << boolalpha <<y << endl;
    return 0;
}

命名空间:namespace
原因:区分重名 变量 函数
A::X
B::F1()

eg1:

#include <iostream>
using namespace std;
namespace A {
    int x = 1;
    void fun(){
        cout << "A" <<endl;
    }
}
namespace B {
    int x = 2;
    void fun(){
        cout << "B" <<endl;
    }
    void fun2(){
        cout << "2B" <<endl;
    }
}
using namespace B;
int main(int argc, const char * argv[]) {
    // insert code here...
    cout << A::x << endl;
    B::fun();
    fun2();
    return 0;
}

eg2:

//使用一个函数 找出一个整型数组中的最大值 或者最小值
#include <iostream>
using namespace std;
namespace companyA{
    int getMaxorMin(int *arr,int count,bool isMax){
        int temp = arr[0];
        for (int i=1; i<count; i++) {
            if (isMax) {
                if (temp < arr[i]) {
                    temp = arr[i];
                }
            } else {
                if (temp > arr[i]) {
                    temp = arr[i];
                }
            }
        }
        return temp;
    }
}

int main(int argc, const char * argv[]) {
    // insert code here...
    bool isMax = false;
    cin >> isMax; //用户决定是最大值还是最小值
    int arr1[]= {3,5,1,7};
    cout << companyA::getMaxorMin(arr1, 4, isMax) << endl; //直接打印
    return 0;
}

指针 & 引用
#define VS const
函数默认值 & 函数重载
内存管理 (堆中程序员管理)

引用类型:
什么是引用 :就是别名 计算机中 就是变量的别名
能不能只有别名 :不行
对别名和对实体的操作都是一样的效果

对变量类型的引用:
eg:

#include <iostream>
using namespace std;

int main(int argc, const char * argv[]) {
    // insert code here...
    int a = 10;
    int &b =a;
    b = 20;
    cout << a << endl;
    a = 30;
    cout << b << endl;
    
    return 0;
}

结构体类型的引用:
eg:

#include <iostream>
using namespace std;
typedef struct{
    int x;
    int y;
}Coord;
int main(int argc, const char * argv[]) {
    // insert code here...
    Coord c;
    Coord &c1 = c;
    c1.x = 10;
    c1.y = 20;
    cout << c.x << "," << c.y << endl;
    return 0;
}

指针类型的引用:
类型 *&指针引用名 =指针
int a = 10;//整型a为10
int *p = &a;//指针p指向a
int *&q = p;//指针p起了别名q
*q = 20;
q起的是p的别名,操作了p,p指向a ,这时候a被改为20 了
eg1:

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    int a = 3;
    int *p = &a;
    int *&q = p;
    *q = 20;
    cout << a << endl;
    return 0;
}

作用(函数参数):
c函数 作为函数参数 func(&x,&y) void func(int *a,int *b)
C++ func(x,y) func(int &a, int &b)
eg2:

#include <iostream>
using namespace std;
void fun(int &a, int &b){
    int c = 0;
    c = a;
    a = b;
    b = c;
}
int main(int argc, const char * argv[]) {
    // insert code here...
    int x = 10;
    int y = 20;
    cout << x << "," << y << endl;
    fun(x, y);
    cout << x << "," << y << endl;
    return 0;
}

const 与基本数据类型

int x = 3; //变量
变量名 x 存储地址 &x 存储内容3

const int x = 3; //常量
变量名 x 存储地址 &x 存储内容3 //不可以改变了

const 与指针类型
const int *p = NULL;//完全等价
int const *p = NULL;//完全等价
int * const p = NUll;// * const之前 就有区别了

const int * const p = NUll;//完全等价
int const * const p = NUll;//完全等价

//1.
int x = 3;
const int *p = &x;
p = &y;//正确
*p = 4;//错误 因为const 修饰的是 *p 不能修改了

//2.
int x = 3;
int *const p = &x;
P = &y;//错误 因为const 修饰的是 p 不能修改了

//3.
const int x = 3;
const int *const p = &x;
p = &y;//错误 不能修改了
*p = 4; //错误 不能修改了

//4.
const int x = 3;
int *y = &x; //错误 编译器不允许修改 const修饰的变量

const 与引用类型
//1.
int x = 3;
const int &y = x;
x = 10; //正确
y = 20; //错误 const 修饰的是别名 y 不能修改了

const 会检查语法错误 define 不会检查语法错误

const 与函数
void func(const int &a, const int &b) {
a = 10;//报错 无法编译
b = 20;//报错 无法编译
}

C++函数的新特性
参数默认值 void(int i, int j=5,int k = 10);
参数列表的最右端必须要有默认值
eg

#include <iostream>
using namespace std;
void fun(int i=30,int j=20,int k= 10);
int main(int argc, const char * argv[]) {
    // insert code here...
    fun();
    fun(100);
    fun(100,20);
    fun(100,200,300);
    return 0;
}
void fun(int i,int j,int k){
    cout << i <<","<< j <<","<< k << endl;
}

函数重载
前提:在相同的作用域下
用同一函数名定义的多个函数
参数个数和参数类型不同
重载的好处:代码编写起名可以用同一个
eg:

#include <iostream>
using namespace std;
void fun(int i,int j,int k);
void fun(double i,double j);
int main(int argc, const char * argv[]) {
    // insert code here...
    fun(1,2,3);
    fun(1.1,2.2);
    return 0;
}
void fun(int i,int j,int k){
    cout << i <<","<< j <<","<< k << endl;
}
void fun(double i,double j) {
    cout << i <<","<< j <<","<< endl;
}

内联函数
普通函数:main入口->1.调用fun ->2.找到func ->3.执行func ->4.返回结果到调用func处 ->5 结束main
内联函数:编译时将函数体代码和实参代替函数调用语句 节省了 2 4 步骤
关键字:inline

为什么不所有的函数都用内联函数呢
1.内联编译时建议性的,由编译器决定
2.逻辑简单,调用频繁的函数建议使用内联。
3.递归函数无法使用内联函数。

eg:

#include <iostream>
using namespace std;
inline void fun(int i,int j,int k);
inline void fun(double i,double j);
int main(int argc, const char * argv[]) {
    // insert code here...
    fun(1,2,3);
    fun(1.1,2.2);
    return 0;
}
void fun(int i,int j,int k){
    cout << i <<","<< j <<","<< k << endl;
}
void fun(double i,double j) {
    cout << i <<","<< j <<","<< endl;
}

内存管理:
内存的本质是什么 资源
内存由谁管理 操作系统
我们能做什么 申请 归还

申请归还内存资源 就是内存管理

内存的申请和释放
申请内存 new 运算符 int *p = new int;
释放内存 delete 运算符 delete p;

如何申请和释放 块 内存
int *arr = new int[10];
delete []arr;

内存操作的注意事项:
申请和释放内存的其他方式
C语言:
申请 void *malloc(size_t size);
释放 void free(void *memblock);
C++: 不能混搭 配套使用
申请 new
释放 delete
申请内存是否一定成功? 不一定成功
int *p = new int[1000];
if(p == NULL) {
//内存分配失败
}
释放内存需要注意什么:指针置为空
delete p;
P = NULL;//指针置为空 ,如果没有置null 又调用了一次delete 就会出现异常。 因为回收已经回收过的内存了。

eg1:

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    int *p = new int;
    if (NULL == p) {
        return 0;
    }
    *p = 20;
    cout << *p << endl;
    delete p;
    p = NULL;
    return 0;
}

eg2:
#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    int *p = new int(20);
    if (NULL == p) {
        return 0;
    }
    cout << *p << endl;
    delete p;
    p = NULL;
    return 0;
}

eg3:

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    int *p = new int[1000];
    if (NULL == p) {
        return 0;
    }
    p[0] = 10;
    p[1] = 20;
    cout << p[0] <<"," << p[1] << endl;
    delete []p;
    p = NULL;
    return 0;
}

封装 面向过程 -> 面向对象

对象

数据成员 & 成员函数
构造函数 & 析构函数
对象复制 & 对象赋值
对象数组 & 对象指针
this指针

对象:具体的实物
类: class 对对象的抽象
抽象:目的不同 抽象的结果不同

访问限定符:
public:公共的
privite:私有的
protect:保护的

对象的实例化
创建对象的过程
实例化的两种方式
从栈中实例化: 没有使用new
从堆中实例化: 使用了new 需要 deleted

对象成员的访问
栈上: 点语法
堆上: 指针

eg:

#include <iostream>
using namespace std;
class Coordinate {
public:
    int x;
    int y;
    void printX() {
        cout << x << endl;
    }
    void printY() {
        cout << y << endl;
    }
};

int main(int argc, const char * argv[]) {
    // insert code here...
    //栈上
    Coordinate coor;
    coor.x = 10;
    coor.y = 20;
    coor.printX();
    coor.printY();
    
    //堆上
    Coordinate *p = new Coordinate();
    if (NULL == p) {
        return 0;
    }
    p->x = 100;
    p->y = 200;
    p->printX();
    p->printY();
    
    delete p;
    p = NULL;
    return 0;
}

字符串

创建:
1.string s1;//空字符串s1
2.string s2(“ABC”);//字符串s2初始化为ABC
3.string s3(s2);//字符串s3初始化为s2的副本
4.strng s4(n,‘c’);//字符串s4初始化为 ccccc n个c的副本

操作:
1.s.empty() //字符串为空,则返回true
2.s.size() //返回字符串的字符个数
3.s[n] //返回字符串中位置为n的字符
4.s1+s2 //字符串拼接成新串

eg:
/**
1.提示用户输入姓名
2.接收用户的输入
3.向用户问好 hello xxxx
4.告诉用户名字的长度
5.告诉用户名字的首字母是什么
6.如果用户直接输入的是回车,那么告诉用户的输入是空
7.如果用户输入的是imooc,那么告诉用户的校色是一个管理员
*/

#include <iostream>
#include <string>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    cout << "请输入姓名:" << endl;
    string s;
//    cin >> s;//cin不能传入 回车
    getline(cin,s);
    if (s.empty()) {
        cout << "用户的输入是空" << endl;
        return 0;
    }
    cout << "Hello " + s << endl;
    cout << "用户名的长度为: " << s.size() <<endl;
    cout << "用户名首字母是" << s[0] << endl;
    if ("imooc" == s) {
        cout << "用户的角色是一个管理员" <<endl;
    }
}

封装:
面向对象的基本思想:谁做什么 ?
eg:
//定义一个student 类,包含名字和年龄两个数据成员,实例化一个student对象,并打印出其成两个数据成员

#include <iostream>
#include <string>
using namespace std;
class Student{
public:
    void setName(string _name){
        m_strName = _name;
    }
    string getName(){
        return m_strName;
    }
    void setGender(string _gender){
        m_strGender = _gender;
    }
    string getGender() {
        return m_strGender;
    }
    int getScore() {
        return m_iScore;
    }
    void initScore() {
        m_iScore = 0;
    }
    void study(int _score){
        m_iScore +=_score;
    };
private:
    string m_strName;
    string m_strGender;
    int m_iScore;
};
int main(int argc, const char * argv[]) {
    // insert code here...
    Student stu;
    stu.initScore();
    stu.setName("张三");
    stu.setGender("男");
    stu.study(5);
    stu.study(3);
    cout<< stu.getName() << " " << stu.getGender() << " " << stu.getScore() << endl;
    return 0;
}

类内定义和内联函数(inline)

类内定义函数会优先编译成内联函数

类外定义:
成员函数的函数体写在函数外面
分为两种:
同文件类外定义:同一个文件
分文件类外定义:拆分成.h 和.cpp
同文件类外定义:
eg:
/**
定义一个teacher类,要求分别采用同文件类外定义和分文件类外定义的方式完成

数据成员:
名字,
年龄
性别

成员函数:
数据成员的封装函数
授课teach
*/

#include <iostream>
#include <string>
using namespace std;
class Teacher {
public:
    void setName(string _name);
    string getName();
    void setGender(string _gender);
    string getGender();
    void setAge(int _age);
    int getAge();
    void tech();
private:
    string m_strName;
    string m_strGender;
    int m_iAge;
};

void Teacher::setName(string _name) {
    m_strName = _name;
}
string Teacher::getName() {
    return m_strName;
}
void Teacher::setGender(string _gender) {
    m_strGender = _gender;
}
string Teacher::getGender() {
    return m_strGender;
}
void Teacher::setAge(int _age) {
    m_iAge = _age;
}
int Teacher::getAge() {
    return m_iAge;
}
void Teacher::tech() {
    cout << "现在上课" << endl;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    Teacher t;
    t.setName("孔子");
    t.setGender("男");
    t.setAge(30);
    cout << t.getName() << " " << t.getAge() << " " << t.getGender() <<endl;
    t.tech();
    return 0;
}

分文件类外定义

Teach.h

#include <iostream>
#include <string>
using namespace std;
class Teacher {
public:
    void setName(string _name);
    string getName();
    void setGender(string _gender);
    
    string getGender();
    void setAge(int _age);
    int getAge();
    void tech();
private:
    string m_strName;
    string m_strGender;
    int m_iAge;
};

Teach.cpp

#include "Teach.h"
void Teacher::setName(string _name) {
    m_strName = _name;
}
string Teacher::getName() {
    return m_strName;
}
void Teacher::setGender(string _gender) {
    m_strGender = _gender;
}
string Teacher::getGender() {
    return m_strGender;
}
void Teacher::setAge(int _age) {
    m_iAge = _age;
}
int Teacher::getAge() {
    return m_iAge;
}
void Teacher::tech() {
    cout << "现在上课" << endl;
}

main.cpp

/**
 定义一个teacher类,要求分别采用同文件类外定义和分文件类外定义的方式完成
 数据成员:
 名字,
 年龄
 性别
 成员函数:
 数据成员的封装函数
 授课teach
 */
#include <iostream>
#include <string>
#include "Teach.h"
using namespace std;

int main(int argc, const char * argv[]) {
    // insert code here...
    Teacher t;
    t.setName("孔子");
    t.setGender("男");
    t.setAge(30);
    cout << t.getName() << " " << t.getAge() << " " << t.getGender() <<endl;
    t.tech();
    return 0;
}

构造函数

实例化的对象在类中如何存储的?
类中的代码是如何存储的?

对象结构:
内存分区
栈区: int x = 0 ; int *p =NUll; //变量,指针 内存由系统来控制 分配和回收
堆区: int *p = new int[20];// 使用new 存储到堆区 程序员自己管理 delete 回收
全局区: 存储全局变量和静态变量
常量区: string str = “hello”;//字符串和常量
代码区: 存储编译之后的二进制代码

对象的初始化:
有且仅有一次初始化
忘记调用初始化,重复调用初始化。、。。。。灾难
构造函数:对象实例化的时候会被自动调用
1.构造函数与类名同名
2.构造函数没有返回值
3.构造函数可以进行重载
4.实例化对象的时候只用到其中一个构造函数
5.当用户没有定义构造函数的时候,编译器自动生成一个构造函数

分类
1.无参数构造函数
2.有参数构造函数
3.有参数默认值构造函数
eg1.2:

Tech.h

#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class Teacher {
public:
    Teacher();
    Teacher(string name,int age);
    void setName(string _name);
    string getName();
    void setAge(int _age);
    int getAge();
private:
    string m_strName;
    int m_iAge;
};

Tech.cpp

#include "Teach.h"
Teacher::Teacher(){
    m_strName = "jim";
    m_iAge = 5;
    cout << "Teacher()" << endl;
}

Teacher::Teacher(string name,int age) {
    m_strName = name;
    m_iAge = age;
    cout << "Teacher(string name,int age)" << endl;
}
void Teacher::setName(string _name) {
    m_strName = _name;
}
string Teacher::getName() {
    return m_strName;
}
void Teacher::setAge(int _age) {
    m_iAge = _age;
}
int Teacher::getAge() {
    return m_iAge;
}

main.cpp

#include <iostream>
#include <string>
#include "Teach.h"
using namespace std;

int main(int argc, const char * argv[]) {
    // insert code here...
    Teacher t1;//无参数实例化
    Teacher t2("Merry",15);//有参数实例化
    
    cout<< t1.getName() << " " << t1.getAge() << endl;
    cout<< t2.getName() << " " << t2.getAge() << endl;
    return 0;
}


eg3:
    Teacher(string name,int age = 20);
    Teacher t3("jim");

默认构造函数
构造函数初始化列表
初始化列表先于构造函数的执行
只能用户构造函数
可以同时初始化多个数据成员
意义:给const 定义常量

eg:
Tech.h

#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class Teacher {
public:
    Teacher(string name = "jim",int age = 1,int m = 100);
    void setName(string _name);
    string getName();
    void setAge(int _age);
    int getAge();
    int getMax();
private:
    string m_strName;
    int m_iAge;
    const int  m_iMax;
};

Tech.cpp

#include "Teach.h"
Teacher::Teacher(string name,int age ,int m):m_strName(name),m_iAge(age),m_iMax(m)
{
    cout << "Teacher(string name,int age)" << endl;
}
void Teacher::setName(string _name) {
    m_strName = _name;
}
string Teacher::getName() {
    return m_strName;
}
void Teacher::setAge(int _age) {
    m_iAge = _age;
}
int Teacher::getAge() {
    return m_iAge;
}
int Teacher::getMax() {
    return m_iMax;
}

main.cpp

#include <iostream>
#include <string>
#include "Teach.h"
using namespace std;

int main(int argc, const char * argv[]) {
    // insert code here...
    Teacher t2;
    Teacher t3("yam",12,150);
    cout<< t2.getName() << " " << t2.getAge() << " " << t2.getMax() <<endl;
    cout<< t3.getName() << " " << t3.getAge() << " " << t3.getMax() <<endl;
    return 0;
}

拷贝构造函数 引用

Eg:
Tech.h

#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class Teacher {
public:
    Teacher(string name = "jim",int age = 1);
    Teacher(const Teacher &tea);
    void setName(string _name);
    string getName();
    void setAge(int _age);
    int getAge();
private:
    string m_strName;
    int m_iAge;
};


tech.cpp

#include "Teach.h"
Teacher::Teacher(string name,int age):m_strName(name),m_iAge(age)
{
    cout << "Teacher(string name,int age)" << endl;
}
Teacher::Teacher(const Teacher &tea) {
    cout << "Teacher(const Teacher &tea)" << endl;
}
void Teacher::setName(string _name) {
    m_strName = _name;
}
string Teacher::getName() {
    return m_strName;
}
void Teacher::setAge(int _age) {
    m_iAge = _age;
}
int Teacher::getAge() {
    return m_iAge;
}

main.cpp

#include <iostream>
#include <string>
#include "Teach.h"
using namespace std;
void test (Teacher t) {
    
}
int main(int argc, const char * argv[]) {
    // insert code here...
    Teacher t2;
    Teacher t3 = t2;
    Teacher t4(t2);
    test(t2);
    return 0;
}

析构函数:归还系统资源
格式: ~类名()
1.可以自动生成
2.销毁时自动调用
3.没有返回值,没有参数,也不能重载

对象生命周期:
1.申请内存
2.初始化列表
3.构造函数
4.参与运算
5.析构函数
6.释放内存

eg:

Teach.h

#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class Teacher {
public:
    Teacher(string name = "jim",int age = 1);
    Teacher(const Teacher &tea);
    ~Teacher();
    void setName(string _name);
    string getName();
    void setAge(int _age);
    int getAge();
private:
    string m_strName;
    int m_iAge;
};



Tech.cpp

#include "Teach.h"
Teacher::Teacher(string name,int age):m_strName(name),m_iAge(age) {
    cout << "Teacher(string name,int age)" << endl;
}
Teacher::Teacher(const Teacher &tea) {
    cout << "Teacher(const Teacher &tea)" << endl;
}
Teacher::~Teacher() {
    cout << "~Teacher()" << endl;
}
void Teacher::setName(string _name) {
    m_strName = _name;
}
string Teacher::getName() {
    return m_strName;
}
void Teacher::setAge(int _age) {
    m_iAge = _age;
}
int Teacher::getAge() {
    return m_iAge;
}

main.cpp

#include <iostream>
#include <string>
#include "Teach.h"
using namespace std;
void test (Teacher t) {
    
}
int main(int argc, const char * argv[]) {
    // insert code here...
    Teacher t1;//栈
    Teacher t2(t1);//拷贝构造函数
    return 0;
}

总结:
类 、对象
类包含 成员函数 和数据成员 防止重名 可以使用 命名空间
数据成员 有普通数据成员 (char int) string const成员 static数据成员 对象成员
成员函数 属性的封装函数 setAge getAge 一般功能函数 特殊函数 构造函数(拷贝构造函数,默认构造函数) 析构函数
能够函数重载 有默认值 有引用 可以const 修饰
实例化对象 堆中实例化 栈中实例化

C++封装下
1.对象成员
2.对象数组
3.深拷贝 VS 浅拷贝
4.对象指针 VS 对象指针成员
5.this 指针
6. const 对象 常对象 const 函数 常成员函数 const 对象成员 常对象成员

走迷宫 案例

一组对象
对象数组
eg1:

Coordinate.h

#include <stdio.h>
class Coordinate {
public:
    Coordinate();
    ~Coordinate();
public:
    int m_iX;
    int m_iY;
};

Coordinate.cpp

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate() {
    cout << "Coordinate" << endl;
}

Coordinate::~Coordinate() {
    cout << "~Coordinate" << endl;
}

main.cpp

/**
 对象数组
 定义coordinate类
 数据成员: m_iX 和 m_iY
 分别从栈和堆中实例化长度为3的对象数组
 给数组中的元素分别赋值
 遍历两个数组
 */
#include <iostream>
#include <stdlib.h>
#include "Coordinate.h"
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    Coordinate coor[3];
    coor[0].m_iX = 3;
    coor[0].m_iY = 5;
    for (int i=0; i< 3; i++) {
        cout << "coor_x:" << coor[i].m_iX << endl;
        cout << "coor_y:" << coor[i].m_iY << endl;
    }
    
    Coordinate *p = new Coordinate[3];
    if (NULL == p) {
        return 0;
    }
    p[0].m_iX = 7;
    p[0].m_iY = 9;
    p[1].m_iX = 11;
    p[1].m_iY = 13;
    p[2].m_iX = 15;
    p[2].m_iY = 17;
    
    for (int i=0; i <3; i++) {
        cout << "p_x:" << (p+i)->m_iX << endl;
        cout << "p_y:" << (p+i)->m_iY << endl;
    }
    delete [] p;//要指向第一个元素再删除
    p = NULL;
    cout << "Hello, World!\n";
    return 0;
}

对象成员创建和销毁

构建函数使用初始化列表子对象先创建
析构函数先调用主对象析构函数 再调用子对象的析构函数

eg1:

#ifndef Coordinate_h
#define Coordinate_h
#include <stdio.h>
class Coordinate {
public:
    Coordinate(int x, int y);
    ~Coordinate();
public:
    int m_iX;
    int m_iY;
};
#endif /* Coordinate_h */

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y) {
    m_iX = x;
    m_iY = y;
    cout << "Coordinate()"<< " " <<m_iX << " " << m_iY << endl;
}

Coordinate::~Coordinate() {
    cout << "~Coordinate()" << endl;
}

#ifndef Line_h
#define Line_h

#include <stdio.h>
#include "Coordinate.h"
class Line {
public:
    Line(int x1, int y1,int x2,int y2);
    ~Line();
public:
    Coordinate m_CoorA;
    Coordinate m_CoorB;
};
#endif /* Line_h*/

#include "Line.h"
#include <iostream>
using namespace std;
Line::Line(int x1, int y1,int x2,int y2):m_CoorA(x1,y1),m_CoorB(x2,y2){
    cout<< "Line() " << endl;
}

Line::~Line() {
    cout<< "~Line() " << endl;
}


#include <iostream>
#include <stdlib.h>
#include "Line.h"

using namespace std;
int main(int argc, const char * argv[]) {
    Line *line = new Line(1,2,3,4);
    if (NULL == line) {
        return 0;
    }
    delete line;
    line = NULL;
    return 0;
}

有构造函数的对象数组初始化
Coordinate coor[2]{{1,2},{3,4}};

深拷贝和浅拷贝
浅拷贝 共用一份内存
深拷贝 新开辟一份内存 拷贝其值

eg:

#include <stdio.h>
class Array {
public:
    Array(int count);
    Array(const Array &arr);
    ~Array();
    void setCount(int count);
    int getCount();
    void printAddr();
private:
    int m_iCount;
    int *m_pArr;
};
#endif /* Array_h */

#include "Array.h"
#include <iostream>
using namespace std;
Array::Array(int count) {
    m_iCount = count;
    m_pArr = new int(m_iCount);
    cout<< "Array()" <<endl;
}

Array::Array(const Array &arr) {
    m_iCount = arr.m_iCount;
    m_pArr = new int(m_iCount);
    for (int i=0; i < m_iCount; i++) {
        m_pArr[i] = arr.m_pArr[i];
    }
    cout<< "Array(const Array &arr)" <<endl;
}

Array::~Array() {
    delete [] m_pArr;
    m_pArr = NULL;
    cout<< "~Array()" <<endl;
}

void Array::setCount(int count) {
    m_iCount = count;
}

int Array::getCount() {
    return m_iCount;
}

void Array::printAddr(){
    cout << "m_pArr的值是: "<< m_pArr <<endl;
}


/**
 1.定义一个Array类,数据成员为 m_iCount
   成员函数包括数据封装函数,构造函数,拷贝构造函数 和析构函数
 2.增加数据成员m_pArr,并增加m_pArr地址查看函数,同时改造
   构造函数,拷贝构造函数和析构函数,
 */
#include <iostream>
#include <stdlib.h>
#include "Array.h"
using namespace std;
int main(int argc, const char * argv[]) {
    Array arr1(5);
    Array arr2 = Array(arr1);
    arr1.printAddr();
    arr2.printAddr();
    return 0;
}

对象指针

eg:

#ifndef Coordinate_h
#define Coordinate_h
#include <stdio.h>
class Coordinate {
public:
    Coordinate(int x, int y);
    ~Coordinate();
    void printInfo();
public:
    int m_iX;
    int m_iY;
};
#endif /* Coordinate_h */

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y):m_iX(x),m_iY(y) {
    cout << "Coordinate()"<< " " <<m_iX << " " << m_iY << endl;
}

Coordinate::~Coordinate() {
    cout << "~Coordinate()" << endl;
}

void Coordinate::printInfo() {
   cout <<"("<<m_iX << "," << m_iY << ")"<<endl;
}


#include <iostream>
#include <stdlib.h>
#include "Coordinate.h"

using namespace std;
int main(int argc, const char * argv[]) {
    Coordinate *p1 = new Coordinate(10,20);
    Coordinate *p2 = new Coordinate(30,40);
    cout<< p1->m_iX + p2->m_iX << endl; //指针
    cout<< (*p1).m_iX + (*p2).m_iY << endl;//对象指针
    delete p1;
    p1 = NULL;
    delete p2;
    p2 = NULL;
    //栈中
    Coordinate p3(50,60);
    Coordinate *p4 = &p3;
    cout<< p3.m_iX + p3.m_iY << endl;
    cout<< (*p4).m_iX + (*p4).m_iY << endl;//指针对象
    return 0;
}

对象成员指针
eg:

#include <stdio.h>
class Coordinate {
public:
    Coordinate(int x, int y);
    ~Coordinate();
    void printInfo();
public:
    int m_iX;
    int m_iY;
};
#endif /* Coordinate_h */

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y):m_iX(x),m_iY(y) {
    cout << "Coordinate()"<< " " <<m_iX << " " << m_iY << endl;
}

Coordinate::~Coordinate() {
    cout << "~Coordinate()" << endl;
}

void Coordinate::printInfo() {
   cout <<"("<<m_iX << "," << m_iY << ")"<<endl;
}


#include <stdio.h>
#include "Coordinate.h"
class Line {
public:
    Line(int x1,int y1,int x2,int y2);
    ~Line();
    void printInfo();
public:
    Coordinate *m_pCoorA;
    Coordinate *m_pCoorB;
};
#endif /* Line_h*/

#include "Line.h"
#include <iostream>
using namespace std;
Line::Line(int x1,int y1,int x2,int y2){
    m_pCoorA = new Coordinate(x1,y1);
    m_pCoorB = new Coordinate(x2,y2);
    cout<< "Line() " << endl;
}

Line::~Line() {
    delete m_pCoorA;
    m_pCoorA = NULL;
    delete m_pCoorB;
    m_pCoorB = NULL;
    cout<< "~Line() " << endl;
}

void Line::printInfo() {
    cout<< "printInfo()" << endl;
    cout<< "("<<m_pCoorA->m_iX << "," << m_pCoorA->m_iY << ")" <<endl;
    cout<< "("<<m_pCoorB->m_iX << "," << m_pCoorB->m_iY << ")" <<endl;
    
}


#include <iostream>
#include <stdlib.h>
#include "Line.h"

using namespace std;
int main(int argc, const char * argv[]) {
    Line *p =  new Line(1,2,3,4);
    p->printInfo();
    cout << sizeof(p) <<endl;
    cout << sizeof(Line) << endl;
    delete p;
    p = NULL;
    return 0;
}

this指针 指向对象自身数据的指针
eg1:

#include <stdio.h>
class Array {
public:
    Array(int len);
    ~Array();
    void setLen(int len);
    int getLen();
    void printInfo();
private:
    int m_iLen;
};

#include "Array.h"
#include <iostream>
using namespace std;
Array::Array(int len) {
    this->m_iLen = len;
    cout<< "Array()" <<endl;
}

Array::~Array() {
    cout<< "~Array()" <<endl;
}

void Array::setLen(int len) {
    this->m_iLen = len;
}

int Array::getLen() {
    return this->m_iLen;
}

void Array::printInfo(){
    cout << "m_iLen的值是: "<< this->m_iLen <<endl;
}

/**
 定义一个Array类
 数据成员:m_iLen表示数组长度
 成员函数:
   构造函数
   析构函数
   len的封装函数
   信息输出函数 printInfo
 */
#include <iostream>
#include <stdlib.h>
#include "Array.h"
using namespace std;
int main(int argc, const char * argv[]) {
    Array arr1(10);
    arr1.printInfo();
    return 0;
}

eg2:
返回引用
Array & printInfo();

Array & Array::printInfo(){
cout << "m_iLen的值是: "<< this->m_iLen <<endl;
return *this;//临时对象 不是他自身 带上了 & 变为引用 就是自身了
}

Array arr1(10);
arr1.printInfo().setLen(5);
cout << arr1.getLen() << endl;

//形成了链式编程

常对象变量和常成员函数

eg:
#include <stdio.h>
class Coordinate {
public:
    Coordinate(int x, int y);
    ~Coordinate();
    int getX() const;
    int getY() const;
    void printInfo();
private:
    int m_iX;
    int m_iY;
};

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y):m_iX(x),m_iY(y) {
    cout << "Coordinate()"<< " " <<m_iX << " " << m_iY << endl;
}

Coordinate::~Coordinate() {
    cout << "~Coordinate()" << endl;
}

void Coordinate::printInfo() {
   cout <<"("<<m_iX << "," << m_iY << ")"<<endl;
}

int Coordinate::getX() const {
    return m_iX;
}

int Coordinate::getY() const {
    return m_iY;
}

#include <stdio.h>
#include "Coordinate.h"
class Line {
public:
    Line(int x1,int y1,int x2,int y2);
    ~Line();
    void printInfo();
    void printInfo() const;
public:
    const Coordinate m_pCoorA;
    Coordinate m_pCoorB;
};

#include "Line.h"
#include <iostream>
using namespace std;
Line::Line(int x1,int y1,int x2,int y2):m_pCoorA(x1,y1),m_pCoorB(x2,y2){
    cout<< "Line() " << endl;
}

Line::~Line() {
    cout<< "~Line() " << endl;
}

void Line::printInfo() {
    cout<< "printInfo()" << endl;
    cout<< "("<<m_pCoorA.getX() << "," << m_pCoorA.getY() << ")" <<endl;
    cout<< "("<<m_pCoorB.getX() << "," << m_pCoorB.getY() << ")" <<endl;
    
}

void Line::printInfo() const{
    cout<< "printInfo() const" << endl;
    cout<< "("<<m_pCoorA.getX() << "," << m_pCoorA.getY() << ")" <<endl;
    cout<< "("<<m_pCoorB.getX() << "," << m_pCoorB.getY() << ")" <<endl;
}


#include <iostream>
#include <stdlib.h>
#include "Line.h"
using namespace std;
int main(int argc, const char * argv[]) {
    Line line(1,2,3,4);
    line.printInfo();
    
    const Line line1(5,6,7,8);
    line1.printInfo();
    return 0;
}

对象指针和对象引用

#include <stdio.h>
class Coordinate {
public:
    Coordinate(int x, int y);
    ~Coordinate();
    int getX();
    int getY();
    void printInfo() const;
private:
    int m_iX;
    int m_iY;
};

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y):m_iX(x),m_iY(y) {
    cout << "Coordinate()"<< " " <<m_iX << " " << m_iY << endl;
}

Coordinate::~Coordinate() {
    cout << "~Coordinate()" << endl;
}

void Coordinate::printInfo() const{
   cout <<"("<<m_iX << "," << m_iY << ")"<<endl;
}

int Coordinate::getX() {
    return m_iX;
}

int Coordinate::getY() {
    return m_iY;
}

#include <iostream>
#include <stdlib.h>
#include "Coordinate.h"
using namespace std;
int main(int argc, const char * argv[]) {
    Coordinate coor1(1,2);
    Coordinate &coor2 = coor1;
    Coordinate *pCoor = &coor1;
    coor1.printInfo();
    coor2.printInfo();
    pCoor->printInfo();
    
    const Coordinate &coor3 = coor1;
    const Coordinate *pCoor4 = &coor1;
    coor3.printInfo();
    pCoor4->printInfo();
    
    Coordinate coor5(3,5);
    Coordinate coor6(7,9);
    Coordinate *const pCoork = &coor5;
    pCoork->getY();
//    pCoor = coor6;
    pCoork->printInfo();
    return 0;
}

作业
迷宫算法:
左手规则、右手规则

架构描述
迷宫类(MazeMap):墙壁字符 通路字符 迷宫数组
走迷宫的人(MazePerson) 人 朝向 当前位置 前一个位置 人的速度

继承篇
为什么要有继承
如何定义基类和派生类
共有继承
保护继承
私有继承
is a has a
多重继承
多继承
虚继承

什么是继承
内存中的对象
实例化的过程: 先初始化父类 再初始化子类
销毁的过程: 销毁先销毁子类 再销毁父类

eg:

#include <stdio.h>
#include <string>
using namespace std;
class Person {
public:
    Person();
    ~Person();
    void eat();
    string m_strName;
    int m_iAge;
};


#include "Person.h"
#include <iostream>
using namespace std;
Person::Person(){
    cout << "Person()" << endl;
}
Person::~Person() {
    cout << "~Person()" << endl;
}
void Person::eat() {
    cout << "eat()" << endl;
}

#include <stdio.h>
#include "Person.h"

class Worker : public Person {
public:
    Worker();
    ~Worker();
    void work();
    int m_iSalary;
};

#include "Worker.h"
#include <iostream>
using namespace std;
Worker::Worker(){
   cout << "Worker()" << endl;
}

Worker::~Worker() {
   cout << "~Worker()" << endl;
}

void Worker::work(){
    cout << "work()" << endl;
}

#include <iostream>
#include <stdlib.h>
#include "Worker.h"

using namespace std;
int main(int argc, const char * argv[]) {
    Worker *p = new Worker();
    p->m_strName = "jame";
    p->m_iAge = 10;
    p->eat();
    p->m_iSalary = 1000;
    p->work();
    delete p;
    p = NULL;
    return 0;
}

公有继承 class A:public B
保护继承 class A:protected B
私有继承 class A:privaate B

公有继承中的
eg1:
保护继承

#include <stdio.h>
#include <string>
using namespace std;
class Person {
public:
    Person();
    ~Person();
    void eat();
protected:
    int m_iAge;
    string m_strName;
};

#include "Person.h"
#include <iostream>
using namespace std;
Person::Person(){
    cout << "Person()" << endl;
}
Person::~Person() {
    cout << "~Person()" << endl;
}
void Person::eat() {
    cout << "eat()" << endl;
}

#include <stdio.h>
#include "Person.h"

class Worker : public Person {
public:
    Worker();
    ~Worker();
    void work();
    int m_iSalary;
};

#include "Worker.h"
#include <iostream>
using namespace std;
Worker::Worker(){
   cout << "Worker()" << endl;
}

Worker::~Worker() {
   cout << "~Worker()" << endl;
}

void Worker::work(){
    m_strName = "jim";
    m_iAge = 50;
    cout << "work()" << endl;
}

#include <iostream>
#include <stdlib.h>
#include "Worker.h"

using namespace std;
int main(int argc, const char * argv[]) {
    Worker worker;
    worker.work();
    return 0;
}

eg2:
私有继承

#include <stdio.h>
#include <string>
using namespace std;
class Person {
public:
    Person();
    ~Person();
    void eat();
private:
    int m_iAge;
    string m_strName;
};
#endif /* Person_h */

#include "Person.h"
#include <iostream>
using namespace std;
Person::Person(){
    cout << "Person()" << endl;
}
Person::~Person() {
    cout << "~Person()" << endl;
}
void Person::eat() {
    cout << "eat()" << endl;
}

#include <stdio.h>
#include "Person.h"

class Worker : public Person {
public:
    Worker();
    ~Worker();
    void work();
    int m_iSalary;
};

#include "Worker.h"
#include <iostream>
using namespace std;
Worker::Worker(){
   cout << "Worker()" << endl;
}

Worker::~Worker() {
   cout << "~Worker()" << endl;
}

void Worker::work(){
//    m_strName = "jim"; //报错 无法访问
//    m_iAge = 50; //报错 无法访问
    cout << "work()" << endl;
}

保护继承中的
public 变成 protected 成员 私有成员无法访问

私有继承中的
public 和 protected 都变成 private 私有成员无法访问

隐藏
子类同名父类方法,父类隐藏了
eg1:

#include <stdio.h>
#include <string>
using namespace std;
class Person {
public:
    Person();
    ~Person();
    void play();
protected:
    string m_strName;
};


#include "Person.h"
#include <iostream>
using namespace std;
Person::Person(){
    m_strName =  "Merry";
    cout << "Person::Person()" << endl;
}
Person::~Person() {
    cout << "Person::~Person()" << endl;
}
void Person::play() {
    cout << "Person::play()" << endl;
    cout << m_strName << endl;
}

#include "Person.h"
#include <stdio.h>
class Solider: public Person {
public:
    Solider();
    ~Solider();
    void play();
    void work();
protected:
    int m_iAge;
};

#include "Solider.h"
#include <iostream>
using namespace std;
Solider::Solider(){
    cout << "Solider::Solider()" << endl;
}
Solider::~Solider(){
    cout << "Solider::~Solider()" << endl;
}

void Solider::play() {
    cout << "Solider::play()" << endl;
}
void Solider::work(){
    m_strName = "jim";
    m_iAge = 20;
    cout << m_strName << endl;
    cout << m_iAge << endl;
    cout << "Solider::work()" << endl;
}

#include <iostream>
#include <stdlib.h>
#include "Solider.h"

using namespace std;
int main(int argc, const char * argv[]) {
    Solider solider;
    solider.play();
    solider.Person::play();
    return 0;
}

继承关系 is-a
子类对象可以赋值给父类
只能访问到父类的成员函数 和成员变量
虚析构函数
eg:
#include <stdio.h>
#include <string>
using namespace std;
class Person {
public:
    Person(string name = "jim");
    virtual ~Person();
    void play();
protected:
    string m_strName;
};

#include "Person.h"
#include <iostream>
using namespace std;
Person::Person(string name){
    m_strName = name;
    cout << "Person::Person()" << endl;
}
Person::~Person() {
    cout << "Person::~Person()" << endl;
}
void Person::play() {
    cout << "Person::play()" << endl;
    cout << m_strName << endl;
}

#include "Person.h"
#include <stdio.h>
class Solider: public Person {
public:
    Solider(string name = "james", int age = 20);
    virtual ~Solider();
    void play();
    void work();
protected:
    int m_iAge;
};

#include "Solider.h"
#include <iostream>
using namespace std;
Solider::Solider(string name, int age){
    m_strName = name;
    m_iAge = age;
    cout << "Solider::Solider()" << endl;
}
Solider::~Solider(){
    cout << "Solider::~Solider()" << endl;
}

void Solider::play() {
    cout << "Solider::play()" << endl;
}
void Solider::work(){
    cout << m_strName <<endl;
    cout << m_iAge << endl;
    cout << "Solider::work()" << endl;
}


#include <iostream>
#include <stdlib.h>
#include "Solider.h"

using namespace std;
void test1(Person p) {
    p.play();
}
void test2(Person &p) {
    p.play();
}
void test3(Person *p) {
    p->play();
}
int main(int argc, const char * argv[]) {
    Solider solider;
//    Person p = solider;
//    p.play();
    Person p;
//    test1(p);
//    test1(solider);
//    test2(p);
//    test2(solider);
    test3(&p);
    test3(&solider);
    return 0;
}

多继承和多重继承
多重继承:子类继承自父类 ,父类还有父类。
多继承:子类 同时有多个父类
class MigrantWorker: public Worker,public Farmer

eg:

#include <stdio.h>
#include <string>
using namespace std;
class Farmer {
public:
    Farmer(string name = "jack");
    virtual ~Farmer();
    void sow();
protected:
    string m_strName;
};

#include "Farmer.h"
#include <iostream>
using namespace std;
Farmer::Farmer(string name ){
    m_strName = name;
    cout << "Farmer::Farmer(string name )" << endl;
}
Farmer::~Farmer() {
    cout << "Farmer::~Farmer()" << endl;
}
void Farmer::sow() {
   cout << m_strName << endl;
   cout << "Farmer::~sow()" << endl;
}

#include <stdio.h>
#include <string>
using namespace std;
class Worker  {
public:
    Worker(string code = "001");
    virtual ~Worker();
    void carry();
protected:
    string m_sCode;
};

#include "Worker.h"
#include <iostream>
using namespace std;
Worker::Worker(string code){
   m_sCode = code;
   cout << "Worker::Worker(string code)" << endl;
}

Worker::~Worker() {
   cout << "Worker::~Worker()" << endl;
}

void Worker::carry(){
    cout << m_sCode << endl;
    cout << "Worker::carry()" << endl;
}

#include <stdio.h>
#include "Worker.h"
#include "Farmer.h"
class MigrantWorker :public Farmer, public Worker{
public:
    MigrantWorker(string name,string code);
    ~MigrantWorker();
};

#include "MigrantWorker.h"
#include <iostream>
using namespace std;
MigrantWorker::MigrantWorker(string name,string code):Farmer(name),Worker(code){
    cout << "MigrantWorker::MigrantWorker(string name,string code):Farmer(name),Worker(code)" << endl;
}

MigrantWorker::~MigrantWorker(){
    cout << "MigrantWorker::~MigrantWorker()" << endl;
}


#include <iostream>
#include <stdlib.h>
#include "MigrantWorker.h"

using namespace std;
int main(int argc, const char * argv[]) {
    MigrantWorker *p = new MigrantWorker("Merry","100");
    p->carry();
    p->sow();
    delete p;
    p = NULL;
    return 0;
}

多继承和多重继承的烦恼

菱形继承

虚继承
virtual使得顶层父类用了默认参数的创建,并且只会生成一次

//区分其他文件 防止重定义

#ifndef Person_h
#define Person_h

#include <stdio.h>
#include <string>
using namespace std;
class Person {
public:
    Person(string color = "blue");
    virtual ~Person();
    void printColor();
protected:
    string m_strColor;
};
#endif /* Person_h */

#include "Person.h"
#include <iostream>
using namespace std;
Person::Person(string color){
    m_strColor = color;
    cout << "Person::Person(string color)" << endl;
}
Person::~Person() {
    cout << "Person::~Person()" << endl;
}
void Person::printColor() {
    cout << m_strColor << endl;
    cout << "Person::printColor()" << endl;
}

#ifndef Farmer_h
#define Farmer_h

#include <stdio.h>
#include <string>
#include "Person.h"
using namespace std;
class Farmer:virtual public Person {
public:
    Farmer(string name = "jack",string color="blue");
    virtual ~Farmer();
    void sow();
protected:
    string m_strName;
};
#endif /* Farmer_h */

#include "Farmer.h"
#include <iostream>
using namespace std;
Farmer::Farmer(string name ,string color):Person("Farmer "+color){
    m_strName = name;
    cout << "Farmer::Farmer(string name )" << endl;
}
Farmer::~Farmer() {
    cout << "Farmer::~Farmer()" << endl;
}
void Farmer::sow() {
   cout << m_strName << endl;
   cout << "Farmer::~sow()" << endl;
}

#ifndef Worker_h
#define Worker_h

#include <stdio.h>
#include <string>
#include "Person.h"
using namespace std;
class Worker:virtual public Person  {
public:
    Worker(string code = "001",string color="blue");
    virtual ~Worker();
    void carry();
protected:
    string m_sCode;
};

#endif /* Worker_h */

#include "Worker.h"
#include <iostream>
using namespace std;
Worker::Worker(string code,string color):Person("Woker "+color){
   m_sCode = code;
   cout << "Worker::Worker(string code)" << endl;
}

Worker::~Worker() {
   cout << "Worker::~Worker()" << endl;
}

void Worker::carry(){
    cout << m_sCode << endl;
    cout << "Worker::carry()" << endl;
}

#ifndef MigrantWorker_h
#define MigrantWorker_h

#include <stdio.h>
#include "Worker.h"
#include "Farmer.h"
class MigrantWorker :public Farmer, public Worker{
public:
    MigrantWorker(string name,string code,string color);
    ~MigrantWorker();
};
#endif /* MigrantWorker_h */

#include "MigrantWorker.h"
#include <iostream>
using namespace std;
MigrantWorker::MigrantWorker(string name,string code,string color):Farmer(name,color),Worker(code,color){
    cout << "MigrantWorker::MigrantWorker()" << endl;
}

MigrantWorker::~MigrantWorker(){
    cout << "MigrantWorker::~MigrantWorker()" << endl;
}

#include <iostream>
#include <stdlib.h>
#include "MigrantWorker.h"

using namespace std;
int main(int argc, const char * argv[]) {
    MigrantWorker *p = new MigrantWorker("Merry","100","yellow");
    p->Farmer::printColor();
    p->Worker::printColor();
    delete p;
    p = NULL;
    return 0;
}

多态篇
普通虚函数
虚析构函数
纯虚函数(抽象类 接口类)
RTTI(运行时类型识别)
异常处理
隐藏和覆盖
早绑定和晚绑定
虚函数表

什么是多态:
静态多态(早绑定)(同一个类 同名方法 根据参数不同进行处理)
动态多态(晚绑定) (以继承为基础 多个子类有同名方法 子类实例化 父类作为接受者 调用同名方法) (虚函数 virtual 不用虚函数 则调用的是父类实现)

eg:

#ifndef Shape_h
#define Shape_h

#include <stdio.h>
#include <iostream>
using namespace std;
class Shape {
public:
    Shape();
    ~Shape();
    virtual double calcArea();
};
#endif /* Shape_h*/

#include "Shape.h"
Shape::Shape() {
    cout<<"Shape::Shape()"<<endl;
}
Shape::~Shape() {
    cout<<"Shape::~Shape()"<<endl;
}
double Shape::calcArea() {
    cout<<"Shape::calcArea()"<<endl;
    return 0;
}

#ifndef Rect_h
#define Rect_h

#include "Shape.h"

class Rect: public Shape {
public:
    Rect(double width,double height);
    ~Rect();
    double calcArea();
protected:
    double m_dWidth;
    double m_dHeight;
};

#endif /* Rect_h */

#include "Rect.h"
Rect::Rect(double width,double height) {
    m_dHeight = height;
    m_dWidth = width;
    cout <<"Rect::Rect()" << endl;
}
Rect::~Rect() {
    cout <<"Rect::~Rect()" << endl;
}
double Rect::calcArea() {
    cout <<"Rect::caleArea()" << endl;
    return  m_dWidth *m_dHeight;
}

#ifndef Circle_h
#define Circle_h
#include "Shape.h"
class Circle : public Shape {
public:
    Circle(double r);
    ~Circle();
    double calcArea();
protected:
    double m_dR;
};
#endif /* Circle_hpp */

#include "Circle.h"
Circle::Circle(double r) {
    m_dR = r;
    cout << "Circle::Circle()" <<endl;
}
Circle::~Circle() {
    cout << "Circle::~Circle()" <<endl;
}
double Circle::calcArea() {
    cout << "Circle::calcArea()" <<endl;
    return 3.14 *m_dR *m_dR;
}


#include <iostream>
#include <string>
#include "Rect.h"
#include "Circle.h"
using namespace std;

int main(int argc, const char * argv[]) {
    // insert code here...
    Shape *shape1 = new Rect(3,6);
    Shape *shape2 = new Circle(5);
    
    shape1->calcArea();
    shape2->calcArea();
    
    delete shape1;
    shape1 = NULL;
    delete shape2;
    shape2 = NULL;
    return 0;
}

多态中的问题:
子类里面包含了指针的成员变量 构造的时候new出指针对象 子类析构的时候会调用delete 来销毁指针对象
但多态情况下,父类作为接受者,析构只会析构父类的析构函数,无法执行到子类的析构函数,就会造成内存泄漏了

为了解决这个问题 ,引入了虚析构函数
用virtual 来修饰析构函数 这样析构的时候 会销毁对应的子类析构函数之后再调用父类析构函数

virtual的使用限制 virtual只和类有关
1.不能修饰普通函数。只能是成员函数
2.不能修饰静态成员函数
3.不能修饰内联函数
4.不能修饰构造函数

eg:

#ifndef Coordinate_h
#define Coordinate_h

#include <stdio.h>
class Coordinate {
public:
    Coordinate(int x,int y);
    ~Coordinate();
private:
    int m_iX;
    int m_iY;
};
#endif /* Coordinate_h */

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y) {
    cout<< "Coordinate::Coordinate()"<<endl;
    m_iX = x;
    m_iY = y;
}

Coordinate::~Coordinate() {
    cout<< "Coordinate::~Coordinate()"<<endl;
}

#ifndef Shape_h
#define Shape_h

#include <stdio.h>
#include <iostream>
using namespace std;
class Shape {
public:
    Shape();
    virtual ~Shape();
    virtual double calcArea();
};
#endif /* Shape_h*/

#include "Shape.h"
Shape::Shape() {
    cout<<"Shape::Shape()"<<endl;
}
Shape::~Shape() {
    cout<<"Shape::~Shape()"<<endl;
}
double Shape::calcArea() {
    cout<<"Shape::calcArea()"<<endl;
    return 0;
}


#ifndef Rect_h
#define Rect_h

#include "Shape.h"

class Rect: public Shape {
public:
    Rect(double width,double height);
    virtual ~Rect();
    virtual double calcArea();
protected:
    double m_dWidth;
    double m_dHeight;
};

#endif /* Rect_h */

#include "Rect.h"
Rect::Rect(double width,double height) {
    m_dHeight = height;
    m_dWidth = width;
    cout <<"Rect::Rect()" << endl;
}
Rect::~Rect() {
    cout <<"Rect::~Rect()" << endl;
}
double Rect::calcArea() {
    cout <<"Rect::caleArea()" << endl;
    return  m_dWidth *m_dHeight;
}


#ifndef Circle_h
#define Circle_h
#include "Coordinate.h"
#include "Shape.h"
class Circle : public Shape {
public:
    Circle(double r);
    virtual ~Circle();
    virtual double calcArea();
protected:
    double m_dR;
    Coordinate *m_pCenter;
};
#endif /* Circle_hpp */

#include "Circle.h"
Circle::Circle(double r) {
    m_dR = r;
    m_pCenter = new Coordinate(3,5);
    cout << "Circle::Circle()" <<endl;
}
Circle::~Circle() {
    delete m_pCenter;
    m_pCenter = NULL;
    cout << "Circle::~Circle()" <<endl;
}
double Circle::calcArea() {
    cout << "Circle::calcArea()" <<endl;
    return 3.14 *m_dR *m_dR;
}



#include <iostream>
#include <string>
#include "Rect.h"
#include "Circle.h"
using namespace std;

int main(int argc, const char * argv[]) {
    // insert code here...
    Shape *shape1 = new Rect(3,6);
    Shape *shape2 = new Circle(5);
    
    shape1->calcArea();
    shape2->calcArea();
    
    delete shape1;
    shape1 = NULL;
    delete shape2;
    shape2 = NULL;
    return 0;
}

虚函数和虚析构函数原理
对象指针
函数指针

实例化一个对象后,除了数据成员 还有一个 虚函数表指针的数据成员
指向一个虚函数表,虚函数表与类定义同时出现,
假设虚函数表起始位是0xccFF
虚函数表指针值就是0xccFF
父类的虚函数表 只有一个
通过父类实例化所有的对象 虚函数表指针的值都是 0xccFF
确保每个对象的虚函数表指针 都指向自己的虚函数表

父类的虚函数表,定义了函数指针
就是计算面积的入口地址,假设是0x3355

调用的时候找到虚函数表指针,再通过指针找到虚函数表
在通过位置偏移找到相应的虚函数的入口地址,就找到了对应的计算面积的函数

如果子类没有定义同名函数
子类从父类中继承了虚函数,就产生了虚函数,虚函数表是子类的虚函数表
起始地址是 0x6688 但是计算面积的函数指针都是 0x3355
保证子类访问父类的计算面积的函数,也能够通过虚函数表指针找到虚函数表,
虚汗树表中找到计算面积的函数指针 也是指向父类的计算面积的函数入口的。

如果子类定义了同名函数
计算面积的函数指针不再是之前的 0x3355
而是子类函数指针覆盖了 父类的函数指针 0x4b2c
如果用shape 的指针 指向了circle 的对象
就会通过circle对象,就会通过circle对象的虚函数表指针
找到虚函数表,再通过circle的虚函数表的偏移量,找到circle 的虚函数的函数入口地址
从而执行子类当中的虚函数
而这就是多态的原理

函数的 覆盖 ==== 隐藏
没有多态的情况下:
出现同名函数 就被称作函数的隐藏
有多态的情况下:
就叫做覆盖,没有子类定义同名虚函数,子类虚函数表上就会写上父类的相应父类的入口地址,
如果子类定义了同名虚函数,子类的虚函数表中就会把原来父类的虚函数表的函数地址就行覆盖,
覆盖成子类的函数地址。

虚析构函数
理论前提:执行完子类的析构函数就会执行父类的析构函数

如果我们在父类当中定义了虚析构函数,我们在父类当中的虚函数表中,就会有一个父类析构函数的函数指针
而在子类的虚函数表中,也会产生一个子类析构函数的函数指针,指向子类的析构函数。
如果使用父类的指针指向子类的对象,通过父类找到子类的虚函数表指针,再找到子类的析构函数,
执行完成之后再执行父类的

证明虚函数表指针的存在
eg1:
没有虚函数的时候

#ifndef Shape_h
#define Shape_h

#include <stdio.h>
#include <iostream>
using namespace std;
class Shape {
public:
    Shape();
    ~Shape();
    double calcArea();
};
#endif /* Shape_h*/

#include "Shape.h"
Shape::Shape() {
}
Shape::~Shape() {
}
double Shape::calcArea() {
    return 0;
}


#ifndef Circle_h
#define Circle_h

#include "Shape.h"
class Circle : public Shape {
public:
    Circle(int r);
    ~Circle();
    double calcArea();
protected:
    int m_IR;
};
#endif /* Circle_h */

#include "Circle.h"
Circle::Circle(int r) {
    m_IR = r;
}
Circle::~Circle() {
}
double Circle::calcArea() {
    return 3.14 *m_IR *m_IR;
}

/**
  虚函数表:
   要求:1.定义Shape类,成员函数:calcArea().构造函数,析构函数
       2.定义Circle类, 成员函数:构造函数,析构函数, 数据成员:m_iR
  概念说明:
    1.对象的大小
    2.对象的地址
    3.对象成员的地址
    4.虚函数表指针
 */
#include <iostream>
#include <string>
#include "Shape.h"
#include "Circle.h"

using namespace std;

int main(int argc, const char * argv[]) {
    // insert code here...

    Shape shape;//如果一个类没有成员变量 一个对象一定要标明自己的存在 会用1个内存单元来标定存在 所以为1
    cout<< sizeof(shape) << endl;
    int *p = (int *)&shape;
    cout << p << endl;//打印shape的地址
    
    Circle circle(100);//如果有成员变量 会按照成员变量的大小来标定 这里只有m_IR int类型的成员变量 所以为4
    cout << sizeof(circle) << endl;
    int *q = (int *)&circle;
    cout << q << endl;//打印circle的地址
    cout <<(unsigned int)(*q) << endl;//打印circle 的地址对应存储的内存 理论上是 m_IR 的100
    return 0;
}

eg2:

#ifndef Shape_h
#define Shape_h

#include <stdio.h>
#include <iostream>
using namespace std;
class Shape {
public:
    Shape();
    ~Shape();
    virtual double calcArea();
};
#endif /* Shape_h*/

#include "Shape.h"
Shape::Shape() {
}
Shape::~Shape() {
}
double Shape::calcArea() {
    return 0;
}

#ifndef Circle_h
#define Circle_h

#include "Shape.h"
class Circle : public Shape {
public:
    Circle(int r);
    ~Circle();
    double calcArea();
protected:
    int m_IR;
};
#endif /* Circle_h */

#include "Circle.h"
Circle::Circle(int r) {
    m_IR = r;
}
Circle::~Circle() {
}
double Circle::calcArea() {
   return 3.14 *m_IR *m_IR;
}


#include <iostream>
#include <string>
#include "Shape.h"
#include "Circle.h"

using namespace std;

int main(int argc, const char * argv[]) {
    // insert code here...

    Shape shape;//现在有virtual calcArea 了 现在应该有8个大小了 64位 32位是4个大小 
    cout<< sizeof(shape) << endl;
    int *p = (int *)&shape;
    cout << p << endl;//打印shape的地址
    cout <<(unsigned int)(*p) << endl;//shape虚函数表的地址
    
    Circle circle(100);//如果有成员变量 会按照成员变量的大小来标定 这里只有m_IR int类型的成员变量 所以为4 + 8 但是有对齐  就是8+8 = 16
    cout << sizeof(circle) << endl;
    int *q = (int *)&circle;
    cout << q << endl;//打印circle的地址
    cout <<(unsigned int)(*q) << endl;//circle虚函数表的地址
    q++;
    q++;//8个字节 到m_IR
    cout <<(unsigned int)(*q) << endl;//打印circle 的地址对应存储的内存 理论上是 m_IR 的100
    return 0;
}

虚函数和纯虚函数
纯虚函数就是没有函数体 同时函数后面加上=0
实现原理:
虚函数表指针 找到虚函数表,偏移找到虚函数 ,如果是普通虚函数 ,就有对应的函数指针
如果是纯虚函数,则对应的函数指针就是0

包含纯虚函数的类就叫做抽象类

抽象类不允许实例化对象。会报错

抽象类的子类也是抽象类的情况下 也不能实例化对象

仅含有纯虚函数的类被称作接口类
无数据成员 只有成员函数,并且都是纯虚函数
接口类跟多的是表达一种能力或者协议

eg:

#ifndef Flyable_h
#define Flyable_h

#include <stdio.h>
class Flable{
public:
    virtual void takeOff() = 0;
    virtual void land() = 0;
};
#endif /* Flyable_h*/


#ifndef Plane_h
#define Plane_h
#include "Flyable.h"
#include <stdio.h>
#include <string>
using namespace std;
class Plane: public Flable {
public:
    Plane(string code);
    virtual void takeOff();
    virtual void land();
    void printCode();
private:
    string m_strCode;
};
#endif /* Plane_h */


#include "Plane.h"
#include <iostream>
using namespace std;
Plane::Plane(string code){
    m_strCode = code;
}

void Plane::takeOff(){
    cout <<"Plane::takeOff()"<<endl;
}

void Plane::land() {
    cout <<"Plane::land()"<<endl;
}

void Plane::printCode(){
    cout <<m_strCode<<endl;
    cout <<"Plane::printCode()"<<endl;
}


#ifndef FighterPlane_h
#define FighterPlane_h

#include <stdio.h>
#include "Plane.h"
class FighterPlane : public Plane {
public:
    FighterPlane(string code);
    virtual void takeOff();
    virtual void land();
};
#endif /* FighterPlane_h */


#include "FighterPlane.h"
#include <iostream>

using namespace std;
FighterPlane::FighterPlane(string code):Plane(code){
    
}
void FighterPlane::takeOff(){
    cout <<"FighterPlane::takeOff()"<<endl;
}
void FighterPlane::land(){
    cout <<"FighterPlane::land()"<<endl;
}


#include <iostream>
#include "FighterPlane.h"

using namespace std;

void flyMatch(Flable *f1,Flable *f2){
    f1->land();
    f1->takeOff();
    f2->land();
    f2->takeOff();
}

int main(int argc, const char * argv[]) {
    // insert code here...
    FighterPlane p1("001");
    Plane p2("002");
    p1.printCode();
    p2.printCode();
    
    flyMatch(&p1, &p2);
    return 0;
}

RTTI(Runtime Type Identification)
运行时类型识别
typeid — dynamic_cast

dynamic_cast注意事项:
1.只能应用于指针和引用的转换
2.要转换的类型中必须包含虚函数
3.转换成功则返回子类的地址,返回失败NULL

typeid注意事项:
1.type_id 返回一个type_info对象的引用
2.如果想通过基类的指针获得派生类的数据类型,基类必须带有虚函数
3.只能获取对象的实际类型

eg:

#include <stdio.h>
class Flable{
public:
    virtual void takeOff() = 0;
    virtual void land() = 0;
};
#endif /* Flyable_h*/

#ifndef Plane_h
#define Plane_h
#include "Flyable.h"
#include <stdio.h>
#include <string>
using namespace std;
class Plane: public Flable {
public:
    virtual void takeOff();
    virtual void land();
    void carry();
};
#endif /* Plane_h */

#include "Plane.h"
#include <iostream>
using namespace std;
void Plane::takeOff(){
    cout <<"Plane::takeOff()"<<endl;
}

void Plane::land() {
    cout <<"Plane::land()"<<endl;
}

void Plane::carry(){
    cout <<"Plane::carry()"<<endl;
}



#ifndef Bird_h
#define Bird_h

#include <stdio.h>
#include "Flyable.h"

class Bird: public Flable {
public:
    void foraging();//觅食
    virtual void takeOff();
    virtual void land();
};
#endif /* Bird_h */

#include "Bird.h"
#include <iostream>
using namespace std;
void Bird::foraging(){
    cout << "Bird::foraging()" << endl;
}

void Bird::takeOff(){
    cout << "Bird::takeOff()" << endl;
}

void Bird::land(){
    cout << "Bird::land()" << endl;
}


#include <iostream>
#include "Bird.h"
#include "Plane.h"

using namespace std;

void doSomeThing(Flable *obj){
    cout << "name: "<<typeid(*obj).name() << endl;
    obj->takeOff();
    if (typeid(*obj) == typeid(Bird)) {
        Bird *bird = dynamic_cast<Bird *>(obj);
        bird->foraging();
    }
    if (typeid(*obj) == typeid(Plane)) {
        Plane *plane = dynamic_cast<Plane *>(obj);
        plane->carry();
    }
    obj->land();
}

int main(int argc, const char * argv[]) {
    // insert code here...
    Bird b;
    doSomeThing(&b);
    Plane a;
    doSomeThing(&a);
    return 0;
}

程序在运行过程中出现的错误
异常处理 对有可能发生异常的地方做出预见性的安排

尝试 捕获 抛出异常
try catch throw

主逻辑与异常处理逻辑分离
try catch 是一对多的关系
catch(…)可以捕获所有的异常

常见的异常:
数组下标越界
除数为0
内存不足

eg1:

using namespace std;
void test()
{
    throw 0.1;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    try {
        test();
    } catch (double &e) {
        cout << e << endl;
    }
    return 0;
}

eg2:

#ifndef Exception_h
#define Exception_h

#include <stdio.h>
class Exception{
public:
    virtual void printException();
    virtual ~Exception(){}
};
#endif /* Exception_h */

#include "Exception.h"
#include <iostream>
using namespace std;
void Exception::printException(){
    cout << "Exception::printException" << endl;
}


#ifndef IndexException_h
#define IndexException_h

#include "Exception.h"
class IndexException : public Exception {
public:
    virtual void printException();  
};
#endif /* IndexException_h */

#include "IndexException.h"
#include <iostream>
using namespace std;
void IndexException::printException() {
    cout <<"提示:下标越界" << endl;
}


#include <iostream>
#include "IndexException.h"
#include <stdlib.h>

using namespace std;
void test()
{
    throw IndexException();
}

int main(int argc, const char * argv[]) {
    // insert code here...
    try {
        test();
    } catch (Exception &e) {
        e.printException();
    }
    return 0;
}

模板

友元函数
友元类

标准模板类
模板类
模板函数

静态数据成员
静态成员函数

运算符重载

友元函数
全局函数:友元全局函数
类的成员函数:友元成员函数

关键字 :friend

直接访问私有成员

1.友元全局函数

#ifndef Time_h
#define Time_h

#include <stdio.h>
#include <iostream>

class Time {
    friend void printTime(Time &t);
public:
    Time(int hour,int min,int sec);
private:
    int m_iHour;
    int m_iMinute;
    int m_iSecond;
};
#endif /* Time_h */



#include "Time.h"
Time::Time(int hour,int min,int sec) {
    m_iHour = hour;
    m_iMinute = min;
    m_iSecond = sec;
}


#include <iostream>
#include "Time.h"
#include <stdlib.h>

using namespace std;
void printTime(Time &t)
{
    cout <<t.m_iHour <<":"<< t.m_iMinute <<":"<<t.m_iSecond <<endl;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    Time t(6,34,35);
    printTime(t);
    return 0;
}



2.友元成员函数
#ifndef Time_h
#define Time_h

#include <stdio.h>
#include <iostream>
#include "Match.h"

class Time {
    friend void Match::printTime(Time &t);
public:
    Time(int hour,int min,int sec);
private:
    int m_iHour;
    int m_iMinute;
    int m_iSecond;
};
#endif /* Time_h */


#include "Time.h"
Time::Time(int hour,int min,int sec) {
    m_iHour = hour;
    m_iMinute = min;
    m_iSecond = sec;
}


#ifndef Match_h
#define Match_h

#include <stdio.h>
class Time;
class Match
{
public:
    void printTime(Time &t);
};
#endif /* Match_h */



#include "Match.h"
#include "Time.h"
#include <iostream>

using namespace std;
void Match::printTime(Time &t)
{
    cout <<t.m_iHour <<":"<< t.m_iMinute <<":"<<t.m_iSecond <<endl;
}


#include <iostream>
#include "Time.h"
#include <stdlib.h>
#include "Match.h"

using namespace std;

int main(int argc, const char * argv[]) {
    // insert code here...
    Time t(6,34,35);
    Match m;
    m.printTime(t);
    return 0;
}

友元类
友元关系不可传递
友元关系的单向性
友元声明的形式以及数量不受限制

友元只是封装的补充

#ifndef Time_h
#define Time_h

#include <stdio.h>
#include <iostream>
class Match;
class Time {
    friend Match;
public:
    Time(int hour,int min,int sec);
private:
    void printTime();
    int m_iHour;
    int m_iMinute;
    int m_iSecond;
};
#endif /* Time_h */

#include "Time.h"
#include <iostream>
using namespace std;

Time::Time(int hour,int min,int sec) {
    m_iHour = hour;
    m_iMinute = min;
    m_iSecond = sec;
}

void Time::printTime(){
    cout <<m_iHour <<":"<< m_iMinute <<":"<<m_iSecond <<endl;
}


#ifndef Match_h
#define Match_h

#include <stdio.h>
#include "Time.h"

class Match
{
public:
    Match(int hour,int min,int sec);
    void testTime();
private:
    Time m_tTimer;
};
#endif /* Match_h */


#include "Match.h"
#include <iostream>

using namespace std;

Match::Match(int hour,int min,int sec):m_tTimer(hour, min, sec){
}

void Match::testTime(){
    m_tTimer.printTime();
    cout <<m_tTimer.m_iHour <<"时"<< m_tTimer.m_iMinute <<"分"<<m_tTimer.m_iSecond <<endl;
}


#include <iostream>
#include "Time.h"
#include <stdlib.h>
#include "Match.h"

using namespace std;

int main(int argc, const char * argv[]) {
    // insert code here...
    Match m(6,34,35);
    m.testTime();
    return 0;
}

const 关键字
常数据成员
常成员函数

static 静态
静态数据成员
静态成员函数

静态数据成员必须单独初始化
静态成员函数不能调用非静态成员函数和非静态数据成员

#ifndef Tank_h
#define Tank_h

#include <stdio.h>
class Tank {
public:
    Tank(char code);
    ~Tank();
    void fire();
    static int getCount();
private:
    static int s_iCount;
    char m_cCode;
};
#endif /* Tank_h */

#include "Tank.h"
#include <iostream>

using namespace std;

int Tank::s_iCount = 0;

Tank::Tank(char code) {
    m_cCode = code;
    s_iCount++;
    cout << "Tank()" << endl;
}

Tank::~Tank() {
    s_iCount--;
    cout << "~Tank()" << endl;
}

void Tank::fire() {
    cout << "Tank--fire()"  << endl;
}

int Tank::getCount() {
    return s_iCount;
}


#include <iostream>
#include <stdlib.h>
#include "Tank.h"

using namespace std;

int main(int argc, const char * argv[]) {
    // insert code here...
    cout<<Tank::getCount()<<endl;
    Tank *p = new Tank('A');
    cout<<Tank::getCount()<<endl;
    Tank *q = new Tank('B');
    cout<<Tank::getCount()<<endl;
    delete p;
    p = NULL;
    delete q;
    q = NULL;
    cout<<Tank::getCount()<<endl;
    return 0;
}

运算符重载
给原有的运算符赋予新的功能
+

1+1 = 2

加法 字符串重载
str1 +str2 = str3

一元运算符重载:只需要一个操作数的符号

-(负号)负号的重载

++符号的重载

负号:

成员函数重载
友元函数重载

前置重载
++1
后置重载
1++

eg1:成员函数重载

#ifndef Coordinate_h
#define Coordinate_h

#include <stdio.h>
class Coordinate {
public:
    Coordinate(int x,int y);
    ~Coordinate();
    
    Coordinate &operator-();
    int getX();
    int getY();
private:
    int m_iX;
    int m_iY;
};
#endif /* Coordinate_h */

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y) {
    cout<< "Coordinate::Coordinate()"<<endl;
    m_iX = x;
    m_iY = y;
}

Coordinate::~Coordinate() {
    cout<< "Coordinate::~Coordinate()"<<endl;
}
 
int Coordinate::getX() {
    return m_iX;
}

int Coordinate::getY() {
    return m_iY;
}

Coordinate &Coordinate::operator-()
{
    this->m_iX = -this->m_iX;
    this->m_iY = -this->m_iY;
    return *this;
}


#include <iostream>
#include <stdlib.h>
#include "Coordinate.h"
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    Coordinate coor(1,3);
    cout <<"("<< coor.getX() << "," <<coor.getY() <<")"<< endl;
    -coor;//coor.operator-()
    cout <<"("<< coor.getX() << "," <<coor.getY() <<")"<< endl;
    return 0;
}

eg2: 友元函数重载

#ifndef Coordinate_h
#define Coordinate_h

#include <stdio.h>
class Coordinate {
    friend Coordinate &operator-(Coordinate &c);
public:
    Coordinate(int x,int y);
    ~Coordinate();
    
    int getX();
    int getY();
private:
    int m_iX;
    int m_iY;
};
#endif /* Coordinate_h */

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y) {
    cout<< "Coordinate::Coordinate()"<<endl;
    m_iX = x;
    m_iY = y;
}

Coordinate::~Coordinate() {
    cout<< "Coordinate::~Coordinate()"<<endl;
}
 
int Coordinate::getX() {
    return m_iX;
}

int Coordinate::getY() {
    return m_iY;
}

Coordinate &operator-(Coordinate &c)
{
    c.m_iX = -c.m_iX;
    c.m_iY = -c.m_iY;
    return c;
}


#include <iostream>
#include <stdlib.h>
#include "Coordinate.h"
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    Coordinate coor(1,3);
    cout <<"("<< coor.getX() << "," <<coor.getY() <<")"<< endl;
    -coor;//coor.operator-()
    cout <<"("<< coor.getX() << "," <<coor.getY() <<")"<< endl;
    return 0;
}

eg3:前置++

#ifndef Coordinate_h
#define Coordinate_h

#include <stdio.h>
class Coordinate {
    friend Coordinate &operator-(Coordinate &c);
public:
    Coordinate(int x,int y);
    ~Coordinate();
    Coordinate &operator++();
    
    int getX();
    int getY();
private:
    int m_iX;
    int m_iY;
};
#endif /* Coordinate_h */

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y) {
    cout<< "Coordinate::Coordinate()"<<endl;
    m_iX = x;
    m_iY = y;
}

Coordinate::~Coordinate() {
    cout<< "Coordinate::~Coordinate()"<<endl;
}
 
int Coordinate::getX() {
    return m_iX;
}

int Coordinate::getY() {
    return m_iY;
}

Coordinate &operator-(Coordinate &c)
{
    c.m_iX = -c.m_iX;
    c.m_iY = -c.m_iY;
    return c;
}

Coordinate & Coordinate::operator++() {
    m_iX++;
    m_iY++;
    return *this;
}


#include <iostream>
#include <stdlib.h>
#include "Coordinate.h"
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    Coordinate coor(1,3);
    cout <<"("<< coor.getX() << "," <<coor.getY() <<")"<< endl;
    ++coor;//coor.operator-()
    cout <<"("<< coor.getX() << "," <<coor.getY() <<")"<< endl;
    return 0;
}

eg4:后置++

#ifndef Coordinate_h
#define Coordinate_h

#include <stdio.h>
class Coordinate {
    friend Coordinate &operator-(Coordinate &c);
public:
    Coordinate(int x,int y);
    ~Coordinate();
    Coordinate &operator++();
    Coordinate operator++(int);
    
    int getX();
    int getY();
private:
    int m_iX;
    int m_iY;
};
#endif /* Coordinate_h */


#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y) {
    cout<< "Coordinate::Coordinate()"<<endl;
    m_iX = x;
    m_iY = y;
}

Coordinate::~Coordinate() {
    cout<< "Coordinate::~Coordinate()"<<endl;
}
 
int Coordinate::getX() {
    return m_iX;
}

int Coordinate::getY() {
    return m_iY;
}

Coordinate &operator-(Coordinate &c)
{
    c.m_iX = -c.m_iX;
    c.m_iY = -c.m_iY;
    return c;
}

Coordinate & Coordinate::operator++() {
    m_iX++;
    m_iY++;
    return *this;
}

Coordinate Coordinate::operator++(int){
    Coordinate old(*this);
    this->m_iX++;
    this->m_iY++;
    return old;
}


#include <iostream>
#include <stdlib.h>
#include "Coordinate.h"
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    Coordinate coor(1,3);
    cout <<"("<< coor.getX() << "," <<coor.getY() <<")"<< endl;
    cout <<"("<< (coor++).getX() << "," <<(coor++).getY() <<")"<< endl;
    cout <<"("<< coor.getX() << "," <<coor.getY() <<")"<< endl;
    return 0;
}


Coordinate::Coordinate()
(1,3)
(1,4)
Coordinate::~Coordinate()
Coordinate::~Coordinate()
(3,5)
Coordinate::~Coordinate()
Program ended with exit code: 0

二元运算符重载

+运算符
成员函数重载
友元函数重载

<<输出运算符
友元函数重载

[]索引运算符
成员函数重载

eg1:
+运算符
成员函数重载

#ifndef Coordinate_h
#define Coordinate_h

#include <stdio.h>
class Coordinate {
    friend Coordinate &operator-(Coordinate &c);
public:
    Coordinate(int x,int y);
    ~Coordinate();
    Coordinate &operator++();
    Coordinate operator++(int);
    Coordinate operator+(Coordinate c);
    int getX();
    int getY();
private:
    int m_iX;
    int m_iY;
};
#endif /* Coordinate_h */

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y) {
    cout<< "Coordinate::Coordinate()"<<endl;
    m_iX = x;
    m_iY = y;
}

Coordinate::~Coordinate() {
    cout<< "Coordinate::~Coordinate()"<<endl;
}
 
int Coordinate::getX() {
    return m_iX;
}

int Coordinate::getY() {
    return m_iY;
}

Coordinate &operator-(Coordinate &c)
{
    c.m_iX = -c.m_iX;
    c.m_iY = -c.m_iY;
    return c;
}

Coordinate & Coordinate::operator++() {
    m_iX++;
    m_iY++;
    return *this;
}

Coordinate Coordinate::operator++(int){
    Coordinate old(*this);
    this->m_iX++;
    this->m_iY++;
    return old;
}

Coordinate Coordinate::operator+(Coordinate c) {
    Coordinate temp(0,0);
    temp.m_iX = this->m_iX + c.m_iX;
    temp.m_iY = this->m_iY + c.m_iY;
    return temp;
}


#include <iostream>
#include <stdlib.h>
#include "Coordinate.h"
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    Coordinate coor1(1,3);
    Coordinate coor2(2,4);
    Coordinate coor3(0,0);
    coor3 = coor1 + coor2;
    cout << coor3.getX() <<","<<coor3.getY() <<endl;
    return 0;
}

+运算符
友元函数重载

#ifndef Coordinate_h
#define Coordinate_h

#include <stdio.h>
class Coordinate {
    friend Coordinate &operator-(Coordinate &c);
    friend Coordinate operator+(Coordinate c1,Coordinate c2);
public:
    Coordinate(int x,int y);
    ~Coordinate();
    Coordinate &operator++();
    Coordinate operator++(int);
    
    int getX();
    int getY();
private:
    int m_iX;
    int m_iY;
};
#endif /* Coordinate_h */

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y) {
    cout<< "Coordinate::Coordinate()"<<endl;
    m_iX = x;
    m_iY = y;
}

Coordinate::~Coordinate() {
    cout<< "Coordinate::~Coordinate()"<<endl;
}
 
int Coordinate::getX() {
    return m_iX;
}

int Coordinate::getY() {
    return m_iY;
}

Coordinate &operator-(Coordinate &c)
{
    c.m_iX = -c.m_iX;
    c.m_iY = -c.m_iY;
    return c;
}

Coordinate & Coordinate::operator++() {
    m_iX++;
    m_iY++;
    return *this;
}

Coordinate Coordinate::operator++(int){
    Coordinate old(*this);
    this->m_iX++;
    this->m_iY++;
    return old;
}

Coordinate operator+(Coordinate c1,Coordinate c2){
    Coordinate temp(0,0);
    temp.m_iX = c1.m_iX + c2.m_iX;
    temp.m_iY = c1.m_iY + c2.m_iY;
    return temp;
}


#include <iostream>
#include <stdlib.h>
#include "Coordinate.h"
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    Coordinate coor1(1,3);
    Coordinate coor2(2,4);
    Coordinate coor3(0,0);
    coor3 = coor1 + coor2;
    cout << coor3.getX() <<","<<coor3.getY() <<endl;
    return 0;
}

<<输出运算符
友元函数重载

#ifndef Coordinate_h
#define Coordinate_h

#include <stdio.h>
#include <iostream>
using namespace std;
class Coordinate {
    friend Coordinate &operator-(Coordinate &c);
    friend Coordinate operator+(Coordinate c1,Coordinate c2);
    friend ostream &operator<<(ostream &output, Coordinate &coor);
public:
    Coordinate(int x,int y);
    ~Coordinate();
    Coordinate &operator++();
    Coordinate operator++(int);
    
    int getX();
    int getY();
private:
    int m_iX;
    int m_iY;
};
#endif /* Coordinate_h */

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y) {
    cout<< "Coordinate::Coordinate()"<<endl;
    m_iX = x;
    m_iY = y;
}

Coordinate::~Coordinate() {
    cout<< "Coordinate::~Coordinate()"<<endl;
}
 
int Coordinate::getX() {
    return m_iX;
}

int Coordinate::getY() {
    return m_iY;
}

Coordinate &operator-(Coordinate &c)
{
    c.m_iX = -c.m_iX;
    c.m_iY = -c.m_iY;
    return c;
}

Coordinate & Coordinate::operator++() {
    m_iX++;
    m_iY++;
    return *this;
}

Coordinate Coordinate::operator++(int){
    Coordinate old(*this);
    this->m_iX++;
    this->m_iY++;
    return old;
}

Coordinate operator+(Coordinate c1,Coordinate c2){
    Coordinate temp(0,0);
    temp.m_iX = c1.m_iX + c2.m_iX;
    temp.m_iY = c1.m_iY + c2.m_iY;
    return temp;
}

ostream &operator<<(ostream &output, Coordinate &coor){
    output << coor.m_iX <<","<<coor.m_iY;
    return output;
}

#include <iostream>
#include <stdlib.h>
#include "Coordinate.h"
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    Coordinate coor1(1,3);
    Coordinate coor2(2,4);
    Coordinate coor3(0,0);
    coor3 = coor1 + coor2;
    cout << coor3 << endl;
    return 0;
}

[]索引运算符
成员函数重载

#ifndef Coordinate_h
#define Coordinate_h

#include <stdio.h>
#include <iostream>
using namespace std;
class Coordinate {
    friend Coordinate &operator-(Coordinate &c);
    friend Coordinate operator+(Coordinate c1,Coordinate c2);
    friend ostream &operator<<(ostream &output, Coordinate &coor);
public:
    Coordinate(int x,int y);
    ~Coordinate();
    Coordinate &operator++();
    Coordinate operator++(int);
    int operator[](int index);
    
    int getX();
    int getY();
private:
    int m_iX;
    int m_iY;
};
#endif /* Coordinate_h */

#include "Coordinate.h"
#include <iostream>
using namespace std;
Coordinate::Coordinate(int x,int y) {
    cout<< "Coordinate::Coordinate()"<<endl;
    m_iX = x;
    m_iY = y;
}

Coordinate::~Coordinate() {
    cout<< "Coordinate::~Coordinate()"<<endl;
}
 
int Coordinate::getX() {
    return m_iX;
}

int Coordinate::getY() {
    return m_iY;
}

Coordinate &operator-(Coordinate &c)
{
    c.m_iX = -c.m_iX;
    c.m_iY = -c.m_iY;
    return c;
}

Coordinate & Coordinate::operator++() {
    m_iX++;
    m_iY++;
    return *this;
}

Coordinate Coordinate::operator++(int){
    Coordinate old(*this);
    this->m_iX++;
    this->m_iY++;
    return old;
}

Coordinate operator+(Coordinate c1,Coordinate c2){
    Coordinate temp(0,0);
    temp.m_iX = c1.m_iX + c2.m_iX;
    temp.m_iY = c1.m_iY + c2.m_iY;
    return temp;
}

ostream &operator<<(ostream &output, Coordinate &coor){
    output << coor.m_iX <<","<<coor.m_iY;
    return output;
}

#include <iostream>
#include <stdlib.h>
#include "Coordinate.h"
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    Coordinate coor1(1,3);
    Coordinate coor2(2,4);
    Coordinate coor3(0,0);
    coor3 = coor1 + coor2;
    cout << coor3 << endl;
    cout << coor3[0] <<endl;
    cout << coor3[1] <<endl;
    return 0;
}

函数模板
将类型作为参数传递进去
关键字
template 模板
typename
class 这里不是类 而是数据类型

变量作为模板参数

多参数函数模板

函数的模板与重载

eg:

#include <iostream>
#include <stdlib.h>
#include "Coordinate.h"
template <typename T>
void display (T a){
    cout << a << endl;
}
template <typename T,class S>
void display (T t, S s) {
    cout << t <<"," << s <<endl;
}
template <typename T, int Ksize>
void display(T a) {
    for (int i = 0; i< Ksize; i++) {
        cout << a << endl;
    }
}

using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    display<int>(10);
    display<double>(10.89);
    
    display<int,double>(10, 10.89);
    
    display<int,10>(20);
    
    return 0;
}

类模板

#ifndef MyArray_h
#define MyArray_h

#include <stdio.h>
#include <iostream>
using namespace std;
template <typename T, int Ksize, int Kval>
class MyArray {
public:
    MyArray();
    ~MyArray() {
        delete [] m_pArr;
        m_pArr = NULL;
    }
    void display();
private:
    T *m_pArr;
};

template <typename T, int Ksize, int Kval>
MyArray<T, Ksize, Kval>::MyArray(){
    m_pArr = new T[Ksize];
    for (int i=0; i < Ksize; i++) {
        m_pArr[i] = Kval;
    }
}

template <typename T, int Ksize, int Kval>
void MyArray<T, Ksize, Kval>::display(){
    for (int i=0; i < Ksize; i++) {
        cout << m_pArr[i] << endl;
    }
}
#endif /* MyArray_h */

#include <iostream>
#include <stdlib.h>
#include "MyArray.h"

using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    MyArray<int, 5, 6> arr;
    arr.display();
    return 0;
}

C++标准模板
STL: Standard Template Lib

vector 向量
对数组的封装

随机读取数据在常数时间完成

向量的初始化的方式:
vector v1; vector保存类型为T的对象,默认构造函数v1为空
vector v2(v1); v2是v1的一个副本
vector v3(n,i); v3包含n个值为i的元素
vector v4(n); v4包含有初始化元素的n个副本

常用函数:
empty() 判断向量是否为空
begin() 返回向量迭代器首元素
end() 返回向量迭代器末元素 的下一个元素
clear() 清空向量
front() 第一个数据
back() 最后一个数据
size() 获得向量中数据的大小
push_back(elem) 将数据插入向量尾
pop_back() 删除向量尾部数据

迭代器
Iterator 指针 开始指向第一个元素

list 链表
数据的插入速度快

map 映射
key value

eg:
Vector

#include <iostream>
#include <stdlib.h>
#include <vector>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    vector<int> vec;
    vec.push_back(3);
    vec.push_back(4);
    vec.push_back(6);
    cout << vec.size() << endl;
    for (int i = 0; i< vec.size(); i++) {
        cout << vec[i] << endl;
    }
    vec.pop_back();
    cout << vec.size() << endl;
    
    vector<int>::iterator itor = vec.begin();
    cout << *itor << endl;
    cout << "------------- "<< endl;
    for (;itor !=vec.end(); itor++) {
        cout << *itor << endl;
    }
    cout << "------------- "<< endl;
    cout <<vec.front()<< endl;
    cout <<vec.back()<< endl;
    return 0;
}

list

#include <iostream>
#include <stdlib.h>
#include <list>

using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    list<int> list1;
    list1.push_back(4);
    list1.push_back(7);
    list1.push_back(10);
    list<int>::iterator itor = list1.begin();
    for (; itor != list1.end(); itor++) {
        cout << *itor << endl;
    }
    return 0;
}

map

#include <iostream>
#include <stdlib.h>
#include <map>

using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    map<int,string> m;
    pair<int, string>p1(3,"hello");
    pair<int, string>p2(6,"world");
    m.insert(p1);
    m.insert(p2);
//    cout << m[3]<< endl;
//    cout << m[6]<< endl;
    map <int,string>::iterator itor = m.begin();
    for (; itor != m.end(); itor++) {
        cout << itor->first << endl;
        cout << itor->second << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值