C++学习笔记

 1 内存模型-内存四区

1.1 程序运行前

#include <iostream>
using namespace std;
//全局变量
int c = 10;
int d = 10;
//const修饰的全局变量
const int c_a = 10;
int main()
{
	//全局区
	//全局变量,静态变量,常量
	//创建普通局部变量
	int a = 10;
	int b = 10;
	cout << "局部变量a地址" << (int)&a << endl;
	cout << "局部变量b地址" << (int)&b << endl;
	cout << "全局变量c地址" << (int)&c << endl;
	cout << "全局变量d地址" << (int)&d << endl;
	//静态变量 在普通变量前加static,属于静态变量
	static int e = 10;
	static int f = 10;
	cout << "静态变量e地址" << (int)&e << endl;
	cout << "静态变量f地址" << (int)&f << endl;
	//常量
	//字符串常量
	cout << "字符串常量的地址" << (int)&"hello world" << endl;
	//const修饰的变量
	cout << "const修饰的全局变量c_a的地址" << (int)&c_a << endl;
	//const修饰的局部变量
	const int c_b = 10;
	cout << "const修饰的局部变量c_b的地址" << (int)&c_b << endl;
}

运行结果:

局部变量a地址223344228
局部变量b地址223344260
全局变量c地址-170926080
全局变量d地址-170926076
静态变量e地址-170926072
静态变量f地址-170926068
字符串常量的地址-170938984
const修饰的全局变量的地址-170939312
const修饰的局部变量的地址223344292

1.2程序运行后

#include <iostream>
using namespace std;
//栈区数据的注意事项 ---不要返回局部变量地址
//栈区的数据由编译器管理开辟和释放
int * func()
{
    int a = 10; //局部变量   存放在栈区,栈区在函数执行完后自动释放掉
    return &a; //返回局部变量地址
}

int main()
{
    int* p;
    p = func();
    cout << *p << endl;
    cout << *p << endl;
}

1.3 new 操作符

#include <iostream>
using namespace std;
//new 的基本用法
int* func()
{
    //在堆区创建整型数据
    //new返回的是该数据类型的指针;
    int* p = new int(10);
    return p;
}
void test01()
{
    int* p = func();
    cout << *p << endl;
    delete p;
    //cout << *p << endl; 内存已经释放,再次访问就是非法操作,会报错
}

//在堆区利用new开辟数组
void test02()
{
    //创建10整型的数组,在堆区
    int* arr = new int[10]; //10代表数组有10个元素
    for (int i = 0;i < 10; i++)
    {
        arr[i] = i + 100;//给该数组赋值;
    }
    for (int i = 0; i < 10; i++)
    {
        cout << arr[i] << endl;
    }
    //释放数组
    //释放数组是要加[];
    delete[]arr;
}

int main()
{
    test01();
    test02();
}

运行结果:

10
100
101
102
103
104
105
106
107
108
109

2 引用

2.1 引用的基本使用

#include <iostream>
using namespace std;
int a = 10;
//引用的基本语法
//数据类型  &别名=原名
int &b  =  a; 
int main()
{
	b = 20;
	cout << a;
}

运行结果:
20

2.2 引用的注意事项

#include <iostream>
using namespace std;
int main()
{
	int a = 10;
	//引用必须初始化
	int& b = a;
	//引用在初始化后,不可以更改
	int c = 20;
	b = c; //赋值操作,而不是更改
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;
	cout << "c=" << c << endl;
}

运行结果:

a=20
b=20
c=20

2.3 引用做函数参数

#include <iostream>
using namespace std;

//交换函数

//值传递
void mySwap01(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;
}

//地址传递
void mySwap02(int* a, int* b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}

//引用传递
void mySwap03(int &a, int &b)
{
	int temp = a;
	a = b;
	b = temp;
}
int main()
{
	int a = 10, b = 20;
	mySwap01(a, b);
	cout << "mySwap01:a=" << a << endl;
	cout << "mySwap01:b=" << b << endl;
	a = 10, b = 20;
	//值传递不会修改实参
	mySwap02(&a,&b);
	cout << "mySwap02:a=" << a << endl;
	cout << "mySwap02:b=" << b << endl;
	a = 10, b = 20;
	//地址传递会修改实参
	mySwap03(a, b);
	cout << "mySwap03:a=" << a << endl;
	cout << "mySwap03:b=" << b << endl;
	//引用传递会修改实参
}

运行结果:

mySwap01:a=10
mySwap01:b=20
mySwap02:a=20
mySwap02:b=10
mySwap03:a=20
mySwap03:b=10

2.4 引用做函数返回值 

#include <iostream>
using namespace std;
//不要返回局部变量的引用
int& test01()
{
    int a = 10;  //局部变量存放在栈区
    return a;
}
//函数的调用可以作为左值
int& test02()
{
    static int a = 10;  //静态变量存放在全局区 
    return a;
}
int main()
{
    int &a = test01();
    cout << a << endl;  //第一次正确是因为编译器做了一次保留
    cout << a << endl; 
    int& b = test02();
    cout << b << endl;
    test02() = 20; //如果函数的返回值是引用,这个函数的调用可以作为左值
    cout << b << endl;
}

运行结果: 

10
10
10
20
 

 2.5 引用的本质

指针常量(指针是常量);----常量指针(常量的指针);

指针常量:该指针是常量,是一个指向不可改,值可改的指针

常量指针:指向常量的指针,是一个指向可改 ,值不可改的指针

#include <iostream>
using namespace std;
void func(int& ref)
{
	ref = 20; //ref是引用。转换为*ref=100
}
int main()
{
	int a = 10;
	int& ref = a; //自动转换为int *const ref = &a;
	ref = 20; //转换为 *ref=20;
	cout << "a:=" << a << endl;
	cout << "ref:=" << ref << endl;
}

运行结果:

a:=20
ref:=20

2.6 常量引用

#include <iostream>
using namespace std;
//打印数据
void showvalue(const int& val)
{
	//val = 1000;
	cout << "val=" << val << endl;
}
int main()
{
	//int a = 10;
	//加上const之后,编译器将代码修改为 
	//int temp=10;const int & ref = temp;
	const int& ref = 10; //引用必须是一块合法的内存空间
	//ref = 20; //加上const之后变为只读,不可以修改
	int a = 100;
	showvalue(a);
	cout <<"a=" <<a << endl;
}

运行结果:

val=100
a=100


3 函数提高

3.1 函数默认参数

#include <iostream>
using namespace std;
//如果我们自己传入数据,就用自己的数据。如果没用,那么用默认值
int func(int a, int b = 20, int c = 30)
{
	return a + b + c;
}
//int func2(int a,int b=10,int c)
//{
//  return a + b + c;
//}
//注意事项
//1 如果某个位置已经有了默认参数,那么从这个位置往后,从左到右都必须有默认值
//2 如果函数声明有默认参数,函数实现就不能有默认参数
// 声明和实现只能有一个默认参数
//int func2(int a = 10, int b = 10);
int main()
{
	cout << func(10, 20, 30) << endl;
	cout << func(10, 30) << endl;
	cout << func(10) << endl;
//  cout << func2(10,10,10) << endl;
}

//int func2(int a = 10, int b = 10)
//{
//    return a + b;
//}

3.2 函数占位符

#include <iostream>
using namespace std;
//占位参数
void func(int a, int)
{
    cout << "1" << endl;
}
int main()
{
    //func(10);// 没有占位参数不可以调用该函数
    func(10,1);
}

4 类和对象

4.1 构造函数和析构函数

 

4.2 函数的分类以及调用

#include <iostream>
using namespace std;
// 拷贝构造函数调用时机
// 1 使用一个已经创建完毕的对象来初始化一个新对象
// 2 值传递的方式给函数参数传值
// 3 值方式返回局部变量
class Person
{
public:
    int show()
    {
        return age;
    }
    Person()
    {
        age = 0;
        cout << "Preson默认构造函数调用" << endl;
    }
    Person(int a)
    {
        age = a;
        cout << "Preson有参构造函数调用" << endl;
    }
    ~Person()
    {
        cout << "Preson析构函数调用" << endl;
    }
    //拷贝构造函数
    Person(const Person& p)
    {
        age = p.age;
        cout << "Person拷贝构造函数调用" << endl;
    }
private:
    int age;
};
//调用
void test01()
{
    // 1 括号法
    //Person p1;
    //Person p2(10);
    //Person p3(p2);
    //cout << "p1的年龄=" << p1.show() << endl;
    //cout << "p2的年龄=" << p2.show() << endl;
    //cout << "p3的年龄=" << p3.show() << endl;
    // 注意事项
    // 调用默认构造函数时候,不要加()
    // 因为下面这行代码,编译器会认为是一个函数的声明
    // Person p(); 不会认为在创建对象
    // void func();
    // 2 显示法
    //Person p1;
    //Person p2 = Person(10); //有参构造
    //Person p3 = Person(p2); //拷贝构造
    //Person(10); //匿名对象  特点:当前行执行结束后,系统会立即释放掉
    //不要利用拷贝构造函数来初始化匿名对象
    //Person(p3); // 编译器会认为 Person(p3)==Person p3; 重定义!
    // 3 隐式转换法
    //Person p = 10; // 相当于Person P==(10); 有参构造
    //Person p1 = Person (p); //拷贝构造函数
}
int main()
{
    test01();
}

4.3 拷贝构造函数的调用时机

#include <iostream>
using namespace std;
// 拷贝构造函数调用时机
// 1 使用一个已经创建完毕的对象来初始化一个新对象
// 2 值传递的方式给函数参数传值
// 3 值的方式返回局部变量
class Person
{
public:
    int show()
    {
        return age;
    }
    Person()
    {
        age = 0;
        cout << "Person默认构造函数调用" << endl;
    }
    Person(int age)
    {
        this->age = age;
        cout << "Person有参构造函数调用" << endl;
    }
    ~Person()
    {
        cout << "Person析构函数调用" << endl;
    }
    Person(const Person &p)
    {
        age = p.age;
        cout << "Person拷贝构造函数调用" << endl;
    }
private:
    int age;
};
// 1 使用一个已经创建完毕的对象来初始化一个新对象
void test01()
{
    Person p1(20);
    Person p2(p1);
    cout << "p1的年龄=" << p1.show() << endl;
    cout << "p2的年龄=" << p2.show() << endl;
}
// 2 值传递的方式给函数参数传值
void dowork(Person p)
{

}
void test02()
{
    Person p;
    dowork(p); //拷贝构造函数
}
// 3 值的方式返回局部变量
Person dowork02()
{
    Person p1;
    cout << (int*)&p1 << endl;
    return p1;
}
void test03()
{
    Person p = dowork02();
    cout << (int*)&p << endl;
}
int main()
{
    test01();
    test02();
    test03();
}

 4.4 深拷贝与浅拷贝

#include <iostream>
using namespace std;
// 深拷贝与浅拷贝
class Person
{
public:
    int show()
    {
        return age;
    }
    void change(int a)
    {
        age = a;
    }
    Person()
    {
        age = 0;
        cout << "Person的默认构造函数调用" << endl;
    }
    Person(int age,int height)
    {
        this->age = age;
        this->height=new int(height);
        cout << "Person的有参构造函数调用" << endl;
    }
    ~Person()
    {
        //析构代码,将堆区开辟的数据做释放操作
        if (height != NULL)
        {
            delete height;
            height = NULL;
        }
        cout << "Person的析构函数调用" << endl;
    }
    Person(const Person& p)
    {
        cout << "Person拷贝构造函数的调用" << endl;
        age = p.age;
        //height = p.height; 编译器默认实现就是这行代码
        //深拷贝操作
        height = new int(*p.height);
    }
    int age; //年龄
    int* height; //身高
};
void test01()
{
    Person p1(18,160);
    cout << "p1的年龄为:" << p1.show() << " p1的身高为:" << *p1.height << endl;
    cout << "p1地址为:" << (int*)&p1.age << endl;
    Person p2(p1);
    cout << "p2的年龄为:" << p2.show() << " p2的身高为:" << *p2.height << endl;
    cout << "p2地址为:" << (int*)&p2.age << endl;
    p1.change(20);
    cout << "p2的年龄为:" << p2.show() << endl;
}
int main()
{
    test01();
}

 运行结果:

Person的有参构造函数调用
p1的年龄为:18 p1的身高为:160
p1地址为:00000068254FF4F8
Person拷贝构造函数的调用
p2的年龄为:18 p2的身高为:160
p2地址为:00000068254FF528
p2的年龄为:18
Person的析构函数调用
Person的析构函数调用


4.5 类对象作为类成员

#include <iostream>
#include <string>
using namespace std;
//类对象作为类成员
class phone
{
public:
    phone(string pname)
    {
        this->pname = pname;
        cout << "创建手机" << endl;
    }
    //型号
    string pname;
};
class Person
{
public:
    Person(string name, string pname):m_name(name),m_phone(pname)
    {
        cout << "创建人类" << endl;
    }
    //姓名
    string m_name;
    //手机
    phone m_phone;
};
void test01()
{
    Person p("张三", "MAX");
    cout << p.m_name <<"拿着" << p.m_phone.pname << endl;
}
int main()
{
    test01();
}
//先创建“零件”再创建“主体”

4.6 静态成员

#include <iostream>
using namespace std;
//静态成员变量
class Person
{
public:
    //所有对象都共享同一份数据
    //在编译阶段就分配了内存
    //类内声明,类外初始化
    static void func()
    {
        cout << "static void func调用" << endl;
    }
    static int m_A;
};
void test01()
{
    Person p;
    cout << p.m_A;
    Person p2;
    p2.m_A = 200;
    cout << p.m_A;
}
void test02()
{
    Person p;
    //通过对象访问
    cout << p.m_A << endl;  
    //痛过类名进行访问
    cout << Person::m_A << endl;
}
//静态成员函数
//所有对象共享一个函数
//静态成员函数只能访问静态成员变量
void test03()
{
    //通过对象访问
    Person p;
    p.func();
    //通过类名访问
    Person::func();
}
int Person::m_A = 100;
int main()
{
    test01();
}

4.7 this指针的用途 

#include <iostream>
using namespace std;
class Person
{
public:
    //用于解决名称冲突
    Person(int age)
    {
        this->age = age;
    }
    Person& PersonAddAge(Person& p)
    {
        this->age += p.age;
        return *this;
    }
    int age;
};
void test()
{
    Person p1(10);
    Person p2(10);
    //链式思想
    p2.PersonAddAge(p1).PersonAddAge(p1);
    cout << p2.age << endl;
}
int main()
{
    test();
}

4.8 const修饰成员函数

#include <iostream>
using namespace std;
//常函数
class Person
{
public:
    //this指针的本质是指针常量,指针的指向是不可以修改的
    //在成员函数后加const,修饰的是this指针,让指针指向的值也不可以修改
    void showPerson() const
    {
        this->m_B = 100;
        //this->m_A = 100;
        //this=NULL;//this指针是不可以修改指向
    }
    void func()
    {
        m_A = 100;
    }
    int m_A;
    mutable int m_B;// 特殊变量,即使在常函数中,也可以修改这个值,加关键字 mutable
};
void test01()
{
    Person p;
    p.showPerson();
}
//常对象
void test02()
{
    const Person p;//在对象前加const ,变为常对象
    //p.m_A = 100;
    p.m_B = 100;//m_B是特殊值,在常对象下可以修改
    //常对象只能调用常函数
    p.showPerson();
    //p.func();
}
int main()
{
    std::cout << "Hello World!\n";
}

 4.9 友元

4.9.1 全局函数做友元 

#include <iostream>
#include <string>
using namespace std;
class Building
{
    friend void goodGay(Building* building);//可以访问私有成员
public:
    Building()
    {
        m_SittingRoom = "客厅";
        m_BedRoom = "卧室";
    }
    string m_SittingRoom;
private:
    string m_BedRoom;
};
//全局函数
void goodGay(Building* building)
{
    cout << "好基友全局函数 正在访问:" << building->m_SittingRoom << endl;
    cout << "好基友全局函数 正在访问:" << building->m_BedRoom << endl;
}
void test()
{
    Building buiding;
    goodGay(&buiding);
}
int main()
{
    test();
}

4.9.2 类做友元

#include <iostream>
#include <string>
using namespace std;
class Building
{
    friend class goodGay;
public:
    Building();
    string m_SittingRoom;
private:
    string m_BedRoom;

};
class goodGay
{
public:
    goodGay();
    void visit(); //参观函数访问Building中的属性
    Building * building;
};
//类外写成员函数
Building::Building()
{
    m_SittingRoom = "客厅";
    m_BedRoom = "卧室";
}
goodGay::goodGay()
{
    //创建建筑物对象
    building = new Building;
}
void goodGay::visit()
{
    cout << "好基友类正在访问:" << building->m_SittingRoom << endl;
    cout << "好基友类正在访问:" << building->m_BedRoom << endl;
}
void test()
{
    goodGay gg;
    gg.visit();
}
int main()
{
    test();
}

 4.9.3 成员函数做友元

#include <iostream>
#include <string>
using namespace std;
class building;
class goodgay
{
public:
    void visit();//让visit函数可以访问biuding中私有成员
    void visit2();//让visit2不可以访问biuding中私有成员
    goodgay();
    building * Building;
};
class building
{
    friend void goodgay::visit();//告诉编译器 goodday下的visit成员函数作为本类的好朋友,可以访问私有内容
public:
    building()
    {
        sittingroom = "客厅";
        bedroom = "卧室";
    }
    string sittingroom;
private:
    string bedroom;

};
void goodgay::visit()
{
    cout << "visit函数正在访问:" << Building->sittingroom << endl;
    cout << "visit函数正在访问:" << Building->bedroom << endl;
}
void goodgay::visit2()
{
    cout << "visit函数正在访问:" << Building->sittingroom << endl;
    //cout << "visit函数正在访问:" << Building->bedgroom << endl;
}
void test01()
{
    goodgay gg;
    gg.visit();
    gg.visit2();
}
goodgay::goodgay()
{
    Building = new building;
}
int main()
{
    test01();
}

4.10 运算符重载

4.10.1 加号运算符重载

#include <iostream>
using namespace std;
//加号运算符
class Person
{
public:
    //成员函数重载加号
    Person operator+(Person& p)
    {
        Person temp;
        temp.m_A = this->m_A + p.m_A;
        temp.m_B = this->m_B + p.m_B;
        return temp;
    }
    Person operator+(int n)
    {
        Person temp;
        temp.m_A = this->m_A + n;
        temp.m_B = this->m_B + n;
        return temp;
    }
    int m_A, m_B;
};
void test01()
{
    Person p1;
    p1.m_A = 10;
    p1.m_B = 10;
    Person p2;
    p2.m_A = 10;
    p2.m_B = 10;
    //成员函数本质调用
    //Person p3=p1.operator+(p2);
    //全局函数本质调用
    //Person p3=operator+(p1,p2);
    Person p3 = p1 + p2;
    //运算符重载可以发声函数重载
    Person p4 = p1 + 100;
    cout << "p3.m_A=" << p3.m_A << endl;
    cout << "p3.m_B=" << p3.m_B << endl;
    cout << "p4.m_A=" << p4.m_A << endl;
    cout << "p4.m_B=" << p4.m_B << endl;
}
//全局函数重载+号
//Person operator+(Person& p1, Person& p2)
//{
    //Person temp;
    //temp.m_A = p1.m_A + p2.m_A;
    //temp.m_B = p1.m_B + p2.m_B;
    //return temp;
//}
int main()
{
    test01();
}

 4.10.2 左移运算符重载

#include <iostream>
using namespace std;
class Person
{
    friend void test01();
    friend ostream& operator<<(ostream& cout, Person& p);
public:
    //利用成员函数重载左移运算符   p.operator<<(cout) 简化版本 p<<cout
    //不会利用成员函数<<运算符,因为无法实现 cout 在左侧
    //void operator<<(Person &p)
    //{
    //
    //}
private:
    int m_A, m_B;
};
//只能利用全局函数重载左移运算符
ostream &operator<<(ostream &cout,Person &p)  //本质是 operator<<(cout,p)简化cout<<p
{
    cout << "m_A" << p.m_A << "m_B" << p.m_B;
    return cout;
}
void test01()
{
    Person p;
    p.m_A = 10;
    p.m_B = 10;
    cout << p << "hello" << endl;
}
int main()
{
    test01();
}

 4.10.3 递增运算符重载

#include <iostream>
using namespace std;
//重载递增运算符
//自定义整型
class MyInt
{
    friend ostream& operator<<(ostream& cout, MyInt& myint);
public:
    MyInt()
    {
        m_num = 0;
    }
    //重载前置++运算符
    MyInt& operator++()
    {
        //先进行++运算
        m_num++;
        //再返回自身
        return *this;
    }
    //重载后置++运算符
    MyInt operator++(int) //括号中的int代表占位参数,可以用于区分前置和后置递增
    {
        //先记录当时结果
        MyInt temp = *this;
        //后递增
        m_num++;
        return temp;
    }
private:
    int m_num;
};
void test01()
{
    MyInt myint;
    cout << ++myint << endl;
    cout << myint << endl;
}
void test02()
{
    MyInt myint;
    myint++;
    cout << myint << endl;
}
ostream& operator<<(ostream& cout, MyInt & myint)
{
    cout << myint.m_num;
    return cout;
}
int main()
{
    test02();
}
//前置返回引用,后置返回值

 4.10.4 赋值运算符重载

#include <iostream>
using namespace std;
//赋值运算符重载
class Person
{
public:
    Person(int age)
    {
        m_age = new int(age);
    }
    ~Person()
    {
        if (m_age != NULL)
        {
            delete m_age;
            m_age = NULL;
        }
    }
    //重载赋值运算符
    Person & operator=(Person &p)
    {
        //编译器提供的浅拷贝
        //m_age = p.m_age;
        //应该先判断是否有属性再堆区,如果有先释放干净,然后再深拷贝
        if (m_age != NULL)
        {
            delete m_age;
            m_age = NULL;
        }
        //深拷贝
        m_age = new int(*p.m_age);
        //返回对象本身
        return *this;
    }
    int* m_age;
};
void test01()
{
    Person p1(18);
    Person p2(20);
    Person p3(30);
    p3 = p2 = p1;
    p1 = p2;   //赋值操作
    cout << "p1的年龄为:" << *p1.m_age << endl;
    cout << "p2的年龄为:" << *p2.m_age << endl;
    cout << "p3的年龄为:" << *p3.m_age << endl;
}
int main()
{
    test01();
    int a = 10;
    int b = 20;
    int c = 30;
    c = b = a;
    cout << "a=" << a << endl;
    cout << "b=" << b << endl;
    cout << "c=" << c << endl;
}

运行结果:

p1的年龄为:18
p2的年龄为:18
p3的年龄为:18
a=10
b=10
c=10

D:\Study\赋值运算符重载\x64\Debug\赋值运算符重载.exe (进程 29848)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .


4.10.5 关系运算符重载

 

#include <iostream>
#include <string>
using namespace std;
//重载关系运算符
class Person 
{
public:
    Person(string name,int age)
    {
        m_name = name;
        m_age = age;
    }
    //重载==号
    bool operator==(Person& p)
    {
        if (this->m_age == p.m_age && this->m_name == p.m_name)
        {
            return true;
        }
        return false;
    }
    string m_name;
    int m_age;
};
void test01()
{
    Person p1("Tom", 18);
    Person p2("Tom", 18);
    if (p1 == p2)
    {
        cout << "p1和p2是相等的" << endl;
    }
}
int main()
{
    test01();
}

 运行结果:

p1和p2是相等的

4.10.6 函数调用运算符重载 

#include <iostream>
#include <string>
using namespace std;
//函数调用运算符重载
//打印处处类
class MyPrint
{
public:
    //重载函数调用运算符
    void operator()(string test)
    {
        cout << test << endl;
    }
};
void test01() 
{
    MyPrint myprint;
    myprint("1");//由于使用起来非常想函数调用,因此称为仿函数
}
void print(string a)
{
    cout << a << endl;
}
//仿函数非常的灵活,没有固定的写法
//加法类
class MyAdd
{
public:
    int operator()(int num_1,int num_2)
    {
        return num_1 + num_2;
    }
};
void test02()
{
    MyAdd add;
    cout << add(10, 20) << endl;
    //匿名函数对象
    cout << MyAdd()(10, 20) << endl;//匿名对象执行完后立即被释放
}
int main()
{
    test01();
    print("a");
    test02();
}

 运行结果:

1
a
30
30
 

4.11 继承

4.11.1 继承基本语法

#include <iostream>
using namespace std;
//普通实现页面
//Java 页面
//class Java
//{
//public:
//    void header()
//    {
//        cout << " 首页,公开课,登录,注册...(公共头部)" << endl;
//    }
//    void footer()
//    {
//        cout << " 帮助中心,交流合作,站内地图...(公共底部)" << endl;
//    }
//    void left()
//    {
//        cout << " Java Python C++ ...(公共分类列表)" << endl;
//    }
//    void content()
//    {
//        cout << " Java学科视频" << endl;
//    }
//};
Python 页面
//class Python
//{
//public:
//    void header()
//    {
//        cout << " 首页,公开课,登录,注册...(公共头部)" << endl;
//    }
//    void footer()
//    {
//        cout << " 帮助中心,交流合作,站内地图...(公共底部)" << endl;
//    }
//    void left()
//    {
//        cout << " Java Python C++ ...(公共分类列表)" << endl;
//    }
//    void content()
//    {
//        cout << " Python学科视频" << endl;
//    }
//};
C++ 页面
//class Cpp
//{
//public:
//    void header()
//    {
//        cout << " 首页,公开课,登录,注册...(公共头部)" << endl;
//    }
//    void footer()
//    {
//        cout << " 帮助中心,交流合作,站内地图...(公共底部)" << endl;
//    }
//    void left()
//    {
//        cout << " Java Python C++ ...(公共分类列表)" << endl;
//    }
//    void content()
//    {
//        cout << " Cpp学科视频" << endl;
//    }
//};
//继承实现页面
//继承好处:减少重复代码
//公共页面
class BasePage
{
public:
       void header()
       {
           cout << " 首页,公开课,登录,注册...(公共头部)" << endl;
       }
       void footer()
       {
           cout << " 帮助中心,交流合作,站内地图...(公共底部)" << endl;
       }
            void left()
       {
           cout << " Java Python C++ ...(公共分类列表)" << endl;
       }
};
//Java 页面
class Java :public BasePage
{
public:
    void content()
    {
        cout << "Java 学科视频" << endl;
    }
};
//Python 页面
class Python :public BasePage
{
public:
    void content()
    {
        cout << "Python 学科视频" << endl;
    }
};
//C++ 页面
class Cpp :public BasePage
{
public:
    void content()
    {
        cout << "C++ 学科视频" << endl;
    }
};
void test01()
{
    cout << " Java 下载视频页面如下:" << endl;
    Java ja;
    ja.header();
    ja.footer();
    ja.left();
    ja.content();
    cout << "------------------------" << endl;
    cout << " Python 下载视频页面如下:" << endl;
    Java py;
    py.header();
    py.footer();
    py.left();
    py.content();
    cout << "------------------------" << endl;
    cout << " C++ 下载视频页面如下:" << endl;
    Cpp cp;
    cp.header();
    cp.footer();
    cp.left();
    cp.content();
}
int main()
{
    test01();
}

 

4.11.2 继承方式 

 

 4.11.3 继承中的对象模型

#include <iostream>
using namespace std;
//继承中的对像模型
class Base
{
public:
    int m_A;
protected:
    int m_B;
private:
    int m_C;
};
class Son :public Base
{
public:
    int m_D;
};
//利用开发人员命令提示工具查看对象模型
//条转盘符 F:
//跳转文件路径 cd 具体路径下
//查看命名
// c1 /d1 reportSingleClassLayout类名 文件名
void test01()
{

    //16
    //父类中所有非静态成员都会被子类继承下去
    //父类中私有成员属性是被编译器给隐藏了,因此是访问不到的,但是确实是是被继承下去了
    cout << "size of Son=" << sizeof(Son) << endl;
}
int main()
{
    test01();
}

4.11.4 继承中构造和析构顺序 

#include <iostream>
using namespace std;
class Base
{
public:
    Base()
    {
        cout << "Base构造函数" << endl;
    }
    ~Base()
    {
        cout << "Base析构函数" << endl;
    }
};
class Son :public Base
{
public:
    Son()
    {
        cout << "Son构造函数" << endl;
    }
    ~Son()
    {
        cout << "Son析构函数" << endl;
    }
};
int main()
{
    Son a;
}

运行结果:
Base构造函数
Son构造函数
Son析构函数
Base析构函数


4.11.5 继承中同名成员函数处理方式

#include <iostream>
using namespace std;
//继承中同名成员处理
class Base
{
public:
    Base()
    {
        m_A = 100;
    }
    void func()
    {
        cout << "Base-func()调用" << endl;
    }
    void func(int a)
    {
        cout << "Base-func(int a)调用" << endl;
    }
    int m_A;
};
class Son : public Base
{
public:
    Son()
    {
        m_A = 200;
    }
    void func()
    {
        cout << "Son-func()调用" << endl;
    }
    int m_A;
};
//同名成员属性处理
void test01()
{
    Son s;
    cout << " Son下的m_A=" << s.m_A << endl;
    //如果通过子类对象访问父类中同名成员,需要加作用域
    cout << " Base下的m_A=" << s.Base::m_A << endl;
}
void test02()
{
    Son s;
    s.func();//直接调用调用的是子类中的同名成员
    s.Base::func();//调用父类要加作用域
    //子类同名函数会隐藏父类所有同名函数,如果想调用必须加作用域
}
int main()
{
    test02();
}

4.11.6 同名静态函数处理 

#include <iostream>
using namespace std;
//继承中同名静态成员处理方式
class Base
{
public:
    static void func()
    {
        cout << "Base - static void func()调用" << endl;
    }
    static int m_A;
};
int Base::m_A = 100;
class Son :public Base
{
public:
    static void func()
    {
        cout << "Son - static void func()调用" << endl;
    }
    static int m_A;
};  
int Son::m_A = 200;
//同名静态成员属性
void test01()
{
    Son s;
    //通过对象访问数据
    cout << "通过对象访问" << endl;
    cout << "Son 下的 m_A=" << s.m_A << endl;
    cout << "Base 下的 m_A=" << s.Base::m_A << endl;
    //通过类名访问数据
    cout << "通过类名访问" << endl;
    cout << "Son 下的 m_A=" << Son::m_A << endl;
    //第一个::代表通过类名方式访问   第二个::代表访问父类作用域下
    cout << "Base 下的 m_A=" << Son::Base::m_A << endl;
}
//静态成员函数
void test02()
{
    //通过对象访问
    cout << "通过对象访问" << endl;
    Son s;
    s.func();
    s.Base::func();
    //通过类名访问
    cout << "通过类名访问" << endl;
    Son::func();
    Son::Base::func();
}
int main()
{
    test02();
}

4.11.7 多继承语法

#include <iostream>
using namespace std;
class Base1
{
public:
    Base1()
    {
        m_A = 100;
    }
    int m_A;
};
class Base2
{
public:
    Base2()
    {
        m_B = 100;
    }
    int m_B;
};
//子类   需要继承Base1和Base2
//语法 :class 子类:继承方式 父类1,继承方式 父类2...
class Son :public Base1, public Base2
{
public:
    Son()
    {
        m_C = 300;
        m_D = 400;
    }
    int m_C, m_D;
};
void test01()
{
    Son s;
    cout << "sizeof Son" << sizeof(Son) << endl;
}
int main()
{
    test01();
}

4.11.8 菱形继承

#include <iostream>
using namespace std;
//动物类
class Animal
{
public:
    int m_age;
};
//利用虚继承可以解决菱形继承的问题
//在继承之前加 Virtual 面为虚继承
//Animal类称为虚基类
//羊类
class Sheep :virtual public Animal
{

};
//驼类
class camel :virtual public Animal
{

};
//羊驼类
class SheepCamel :public Sheep, public camel
{

};
void test01()
{
    SheepCamel st;
    st.Sheep::m_age = 18;
    st.camel::m_age = 28;
    //当菱形继承,两大父类拥有相同的数据,需要加已作用域区分
    cout << "st.Sheep::m_age =" << st.Sheep::m_age << endl;
    cout << "st.camel::m_age =" << st.camel::m_age << endl;
    cout << "st.m_age =" << st.m_age << endl;
    //这份数据有一份就可以了,菱形继承导致数据有两份,浪费资源
}
int main()
{
    test01();
}

4.12 多态

4.12.1 多态的基本概念

#include <iostream>
using namespace std;
//多态
//动物类
class Animal
{
public:
    //虚函数
    virtual void speak()
    {
        cout << "动物在说话" << endl;
    }
};
//猫类
class Cat :public Animal
{
public:
    //重写 函数返回值类型 函数名 参数列表 完全相同
    void speak()
    {
        cout << "小猫在说话" << endl;
    }
};
//狗类
class Dog :public Animal
{
public:
    //重写 函数返回值类型 函数名 参数列表 完全相同
    void speak()
    {
        cout << "小狗在说话" << endl;
    }
};
//执行说话的函数
//地址早绑定 在编译阶段确定函数地址
//如果想执行让猫说话,那么这个地址就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定

//动态多态满足条件
//1 有继承关系
//2 子类要重写父类的虚函数

//动态多态只用
//父类的指针或引用 执行子类对象
void dospeak(Animal& animal) // Animal & animal=cat;
{
    animal.speak();
}
void test01()
{
    Cat cat;
    dospeak(cat);
    Dog dog;
    dospeak(dog);
}
int main()
{
    test01();
}

运行结果:
小猫在说话
小狗在说话

 

4.12.2 多态的原理刨析 

#include <iostream>
using namespace std;
//多态
//动物类
class Animal
{
public:
    //虚函数
    virtual void speak()
    {
        cout << "动物在说话" << endl;
    }
};
//猫类
class Cat :public Animal
{
public:
    //重写 函数返回值类型 函数名 参数列表 完全相同
    void speak()
    {
        cout << "小猫在说话" << endl;
    }
};
//狗类
class Dog :public Animal
{
public:
    //重写 函数返回值类型 函数名 参数列表 完全相同
    void speak()
    {
        cout << "小狗在说话" << endl;
    }
};
//执行说话的函数
//地址早绑定 在编译阶段确定函数地址
//如果想执行让猫说话,那么这个地址就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定

//动态多态满足条件
//1 有继承关系
//2 子类要重写父类的虚函数

//动态多态只用
//父类的指针或引用 执行子类对象
void dospeak(Animal& animal) // Animal & animal=cat;
{
    animal.speak();
}
void test01()
{
    Cat cat;
    dospeak(cat);
    Dog dog;
    dospeak(dog);
}
void test02()
{
    cout << "sizeof Animal =" << sizeof(Animal) << endl;
}
int main()
{
    test02();
}

4.12.3  多态案例-计算机类

#include <iostream>
using namespace std;
//普通实现
class Calculator
{
public:
    int getResult(string oper)
    {
        if (oper == "+")
        {
            return m_num1 + m_num2;
        }
        else if (oper == "-")
        {
            return m_num1 - m_num2;
        }
        else if (oper == "*")
        {
            return m_num1 * m_num2;
        }
    }
    //如果想扩展新的功能,需要修改源码
    //在真实的开发中 提倡 开闭原则
    //开闭原则:对扩展进行开发,对修改进行关闭
    int m_num1;
    int m_num2;
};
//利用多态实现
//多态好处:
//1 组织结构清晰
//2 可读性强
//3 对于前期和后期扩展以及维护性高
class AbstractCalculator
{
public:
    virtual int getResult()
    {
        return 0;
    }
    int m_num1;
    int m_num2;
};
//加法计算器类
class AddCaculator :public AbstractCalculator
{
public:
    int getResult()
    {
        return m_num1 + m_num2;
    }
};
class SubCaculator :public AbstractCalculator
{
    int getResult()
    {
        return m_num1 - m_num2;
    }
};
class MulCaculator :public AbstractCalculator
{
    int getResult()
    {
        return m_num1 * m_num2;
    }
};
void test01()
{
    //创建一个计算器对象
    Calculator c;
    c.m_num1 = 10;
    c.m_num2 = 10;
    cout << c.m_num1 << "+" << c.m_num2 << "=" << c.getResult("+") << endl;
    cout << c.m_num1 << "-" << c.m_num2 << "=" << c.getResult("-") << endl;
    cout << c.m_num1 << "*" << c.m_num2 << "=" << c.getResult("*") << endl;
}
void test02()
{
    //多态使用条件
    //父类指针或引用指向子类对象
    //加法运算563 1
    AbstractCalculator* abc = new AddCaculator;
    abc->m_num1 = 10;
    abc->m_num2 = 20;
    cout << abc->m_num1 << "+" << abc->m_num2 << "=" << abc->getResult() << endl;
    //用完后记得销毁
    delete abc;
    abc = new SubCaculator;
    abc->m_num1 = 10;
    abc->m_num2 = 20;
    cout << abc->m_num1 << "-" << abc->m_num2 << "=" << abc->getResult() << endl;
}
int main()
{
    test02();
}

 4.12.4 纯虚函数和抽象类

#include <iostream>
using namespace std;
//纯虚函数和抽象类
class Base
{
public:
    //纯虚函数
    //只要有一个春旭函数,这个类就叫做抽象类
    //抽象类特点:
    //1 无法实例化对象
    //2 抽象类的子类 必须要重写符类中的纯虚函数,否则也属于抽象类
    virtual void func() = 0;
};
class Son :public Base
{
public:
    void func() 
    {
        cout << "func 函数调用" << endl;
    };
};
void test01()
{
    //Base b;//抽象类不能实例化对象
    //new base;//抽象类不能实例化对象
    //Son s;//子类必须重写父类纯虚函数,否则无法实例化对象
    Base* base = new Son;
    base->func();
}
int main()
{
    test01();
}

 4.12.5 多态案例-制作饮品

#include <iostream>
using namespace std;
//多态案例 制作饮品
class AbstractDrinking
{
public:
    //煮水
    virtual void Boil() = 0;
    //冲泡
    virtual void Brew() = 0;
    //倒入杯中
    virtual void PourInCup() = 0;
    //加入辅助的佐料
    virtual void PutSomething() = 0;
    //制作饮品
    void makeDrink()
    {
        Boil();
        Brew();
        PourInCup();
        PutSomething();
    }
};
//制作咖啡
class Coffee :public AbstractDrinking
{
public:
    //煮水
    virtual void Boil() 
    {
        cout << "煮水" << endl;
    }
    
    //冲泡
    virtual void Brew()
    {
        cout << "冲泡咖啡" << endl;
    }
    //倒入杯中
    virtual void PourInCup()
    {
        cout << "倒入杯中" << endl;
    }
    //加入辅助的佐料
    virtual void PutSomething()
    {
        cout << "加如牛奶和糖" << endl;
    }
};
//制作茶水
class Tea :public AbstractDrinking
{
public:
    //煮水
    virtual void Boil()
    {
        cout << "煮水" << endl;
    }

    //冲泡
    virtual void Brew()
    {
        cout << "冲泡茶叶" << endl;
    }
    //倒入杯中
    virtual void PourInCup()
    {
        cout << "倒入杯中" << endl;
    }
    //加入辅助的佐料
    virtual void PutSomething()
    {
        cout << "加柠檬和枸杞" << endl;
    }
};
void doWork(AbstractDrinking* abs)
{
    abs->makeDrink();
    delete abs;
}
void test01()
{
    //制作咖啡
    doWork(new Coffee);
    //制作茶水
    doWork(new Tea);
}
int main()
{
    test01();
}

 运行结果:

煮水
冲泡咖啡
倒入杯中
加如牛奶和糖
煮水
冲泡茶叶
倒入杯中
加柠檬和枸杞

4.12.6 虚析构和纯虚析构 

 

#include <iostream>
using namespace std;
//虚析构和纯虚析构
class Animal
{
public:
    Animal()
    {
        cout << "Anima构造函数调用" << endl;
    }
    //利用虚析构可以解决父类释放子类对象是不干净问题
    //virtual~Animal()
    //{
    //    cout << "Animal析构函数调用" << endl;
    //}
    virtual ~Animal() = 0;
    virtual void speak() = 0;
};
Animal:: ~Animal() 
{
    cout << "Animal纯虚析构函数调用" << endl;
}
class Cat :public Animal
{
public:
    Cat() {};
    Cat(string name)
    {
        cout << "Cat的构造函数调用" << endl;
        m_name = new string(name);
    }
    virtual void speak()
    {
        cout <<*m_name<< "小猫在说话" << endl;
    }
    ~Cat()
    {
        if (m_name != NULL)
        {
            cout << "Cat的析构函数调用" << endl;
            delete m_name;
            m_name = NULL;
        }
    }
    string * m_name;
};
void test01()
{
    Animal* animal = new Cat("Tom");
    animal->speak();
    //父类的指针在析构时候,不会调用子类的析构函数,导致子类如果有堆区属性,出现内存泄露
    delete animal;
}
int main()
{
    test01();
}

 运行结果:
Anima构造函数调用
Cat的构造函数调用
Tom小猫在说话
Cat的析构函数调用
Animal纯虚析构函数调用

4.12.7 多态案例-电脑组装

 

#include <iostream>
using namespace std;
//抽象不同零件类
//抽象CPU类
class CPU
{
public:
    //抽象的计算函数
    virtual void calculate() = 0;
};
//抽象GPU类
class GPU
{
public:
    //抽象的显示函数
    virtual void display() = 0;
};
//抽象RAM类
class RAM
{
public:
    //抽象的存储函数
    virtual void storage() = 0;
};
//电脑类
class Computer
{
public:
    Computer(CPU* cpu, GPU* gpu, RAM* ram)
    {
        m_cpu=cpu;
        m_gpu=gpu;
        m_ram=ram;
    }
    ~Computer()
    {
        if (m_cpu != NULL)
        {
            delete m_cpu;
            m_cpu = NULL;
        }
        if (m_gpu != NULL)
        {
            delete m_gpu;
            m_gpu = NULL;
        }
        if (m_ram != NULL)
        {
            delete m_ram;
            m_ram = NULL;
        }
    }
    void work()
    {
        //让零件工作起来,调用接口
        m_cpu->calculate();
        m_gpu->display();
        m_ram->storage();
    }
private:
    CPU* m_cpu;//CPU零件指针
    GPU* m_gpu;//GPU零件指针
    RAM* m_ram;//RAM零件指针
};
//具体厂商
//Intel厂商
class IntelCPU :public CPU
{
public:
    virtual void calculate()
    {
        cout << "Intel的CPU开始计算了!" << endl;
    }
};
class IntelGPU :public GPU
{
public:
    virtual void display()
    {
        cout << "Intel的GPU开始显示了!" << endl;
    }
};
class IntelRAM :public RAM
{
public:
    virtual void storage()
    {
        cout << "Intel的RAM开始存储了!" << endl;
    }
};
//AMD厂商
class AMDCPU :public CPU
{
public:
    virtual void calculate()
    {
        cout << "AMD的CPU开始计算了!" << endl;
    }
};
class AMDGPU :public GPU
{
public:
    virtual void display()
    {
        cout << "AMD的GPU开始显示了!" << endl;
    }
};
class AMDRAM :public RAM
{
public:
    virtual void storage()
    {
        cout << "AMD的RAM开始存储了!" << endl;
    }
};
void test01()
{
    //创建第一台电脑的零件
    CPU* intelCPU = new IntelCPU;
    GPU* intelGPU = new IntelGPU;
    RAM* intelRAM = new IntelRAM;
    CPU* amdCPU = new AMDCPU;
    GPU* amdGPU = new AMDGPU;
    RAM* amdRAM = new AMDRAM;
    //第一台电脑组装
    Computer* computer1 = new Computer(intelCPU, intelGPU, intelRAM);
    cout << "第一台电脑开始工作" << endl;
    computer1->work();
    delete computer1;
    cout << "----------------------" << endl;
    //第二台电脑组装
    Computer* computer2 = new Computer(amdCPU, amdGPU, amdRAM);
    cout << "第二台电脑开始工作" << endl;
    computer2->work();
    delete computer2;
    cout << "----------------------" << endl;
    //第三台电脑组装
    Computer* computer3 = new Computer(new AMDCPU, new AMDGPU, new IntelRAM);
    cout << "第三台电脑开始工作" << endl;
    computer3->work();
    delete computer3;
    cout << "----------------------" << endl;
}
int main()
{
    test01();
}

 运行结果:
第一台电脑开始工作
Intel的CPU开始计算了!
Intel的GPU开始显示了!
Intel的RAM开始存储了!
----------------------
第二台电脑开始工作
AMD的CPU开始计算了!
AMD的GPU开始显示了!
AMD的RAM开始存储了!
----------------------
第三台电脑开始工作
AMD的CPU开始计算了!
AMD的GPU开始显示了!
Intel的RAM开始存储了!
----------------------

5 文件操作

5.1 文本文件

5.1.1 写文件

#include <iostream>
#include <fstream>
using namespace std;
//文本文件 写文件
int main()
{
    //1 包含头文件 fstream
    //2 创建流对象
    ofstream ofs;
    //3 指定打开方式
    ofs.open("test.txt", ios::out);
    //4 写内容
    ofs << "姓名:张三" << endl;
    ofs << "姓别:男" << endl;
    ofs << "年龄:18" << endl;
    //5 关闭文件
    ofs.close();
}

 5.1.2 读文件

 

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
//文本文件 读文件
void test01()
{
    //1 包含头文件
    //2 创建流对象
    ifstream ifs;

    //3 打开文件 并且判断是否打开成功
    ifs.open("test.txt", ios::in);
    if(!ifs.is_open())
    {
        cout << "文件打开失败" << endl;
        return;
    }
    //4 读数据
    //第一种
    /*char buf[1024] = { 0 };
    while (ifs >> buf)
    {
        cout << buf << endl;
    }*/
    //第二种
    /*char buf[1024] = { 0 };
    while (ifs.getline(buf, 1024))
    {
        cout << buf << endl;
    }*/
    //第三种
    /*string buf;
    while (getline(ifs, buf))
    {
        cout << buf << endl;
    }*/
    //第四种
    //char c;
    //while (c == ifs.get() != EOF)//EOF end of file
    //{
    //    cout << c << endl;
    //}
    //5 关闭文件
    ifs.close();
}
int main()
{
    test01();
}

5.2 二进制文件 

5.2.1 写文件

 

#include <iostream>
#include <fstream>
using namespace std;
//二进制文件 写文件
class Person
{
public:
    char m_name[64];
    int m_age;
};
void test01()
{
    //1 包含头文件
    
     
    //2 创建流对象
    ofstream ofs("person.txt", ios::out | ios::binary);
     
    //3 打开文件
    //ofs.open("person.txt",ios::out | ios::binary)
    
    //4 写文件
    Person p = { "张三",18 };
    ofs.write((const char*)&p, sizeof(Person));
     
    //5 关闭文件
    ofs.close();
}
int main()
{
    test01();
}

 5.2.2 读文件

#include <iostream>
#include <fstream>
using namespace std;
//二进制文件 读文件
class Person
{
public:
    char m_name[64];
    int m_age;
};
void test01()
{
    //1 包含头文件


    //2 创建流对象
    ifstream ifs("person.txt", ios::out | ios::binary);

    //3 打开文件 判断文件是否打开成功
    ifs.open("person.txt", ios::in | ios::binary);
        if (!ifs.is_open())
        {
            cout << "文件打开失败" << endl;
            return;
        }
    //4 读文件
    Person p;
    ifs.read((char*)&p, sizeof(Person));
    cout << "姓名:" << p.m_name << "年龄:" << p.m_age << endl;

    //5 关闭文件
    ifs.close();
}
int main()
{
    test01();
}

6 模板

6.1 函数模板

#include <iostream>
using namespace std;
//函数模板
//两个整型交换函数
void swapInt(int& a, int& b)
{
    int temp = a;
    a = b;
    b = temp;
}
//交换两个浮点型函数
void swapDouble(double& a, double& b)
{
    double temp = a;
    a = b;
    b = temp;
}
//函数模板
template<typename T>  //声明一个模板,告诉编译器后面代码中紧跟着的T不要报错,T是一个通用的数据类型
void mySwap(T& a, T& b)
{
    T temp=a;
    a = b;
    b = temp;
}
void test01()
{
    int a = 10, b = 20;
    //利用函数模板交换
    //两种方式使用函数模板
    //1 自动类型推导
    mySwap(a, b);
    //2 显示指定类型
    mySwap<int>(a, b);
    cout << "a=" << a << endl;
    cout << "b=" << b << endl;
    double c = 1.1;
    double e = 2.2;
    swapDouble(c, e);
}
int main()
{
    test01();
}

 6.2 函数模板注意事项

#include <iostream>
using namespace std;
//函数模板注意事项
template<typename T> //typename可以替换class
void mySwap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}
//1 自动类型推导,必须推导出一致的数据类型T才可以使用
void test01()
{
	int a = 10;
	int b = 20;
	char c = 'c';
	mySwap(a, b);//正确!
	//mySwap(a, c);//错误!推导不出来
}
//2 模板必须要确定出T的数据类型,才可以使用
template<class T>
void func()
{
	cout << "func 调用" << endl;
}
void test02()
{
	func<int>();
}
int main()
{
	test02();
}

6.3 函数模板案例

#include <iostream>
using namespace std;\

//时下按通用 对数组进行排序的函数
//规则 从大到小
//算法 选择
//测试 char 数组, int 数组
template<class T>
void mySwap(T& a, T& b)
{
    T temp = a;
    a = b;
    b = temp;
}
//排序算法
template<class T>
void mySort(T arr[],int len)
{
    for (int i = 0; i < len; i++)
    {
        int max = i; //认定最大值的下标
        for (int j = i + 1; j < len; j++)
        {
            if (arr[max] < arr[j])
            {
                max = j;
            }
        }
        if (max != i)
        {
            //交换msx和i的元素
            mySwap(arr[max], arr[i]);
        }
    }
}
//打印数组模板
template<class T>
void printArray(T arr[], int len)
{
    for (int i=0; i < len; i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;
}
void test01()
{
    //测试 char 数组
    char charArr[] = "badcfe1";
    int num = sizeof(charArr) / sizeof(char);
    mySort(charArr, num);
    printArray(charArr, num);
}
int main()
{
    test01();
}

7 STL

7.1 STL的诞生

 

7.2 STL基本概念 

 7.3 STL六大组件

 7.4 STL中容器,算法,迭代器

 

7.5 容器算法迭代器初识

7.5.1  vector存放内置数据类型

 

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void myPrint(int val)
{
    cout << val << endl;
}
void test01()
{
    //创建一个vector容器,数组
    vector<int> v;

    //向容器中插入数据
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);

    //通过迭代器访问容器中的数据
    vector<int>::iterator itBegin = v.begin();//起始迭代器 指向容器中第一个元素
    vector<int>::iterator itEnd = v.end();//结束迭代器 指向容器中最后一个元素的下一个位置

    //第一种的遍历方式
    while (itBegin != itEnd)
    {
        cout << *itBegin << endl;
        itBegin++;
    }

    //第二种的遍历方式
    for (vector<int>::iterator it = v.begin(); it != v.end();it++)
    {
        cout << *it << endl;
    }

    //第三种的遍历方式 利用STL中的遍历算法
    for_each(v.begin(),v.end(), myPrint);
}
int main()
{
    test01();
}
7.5.2 vector存放自定义数据类型
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Person
{
public:
    Person(string name, int age)
    {
        this->m_name = name;
        this->m_age = age;
    }
    string m_name;
    int m_age;
};
void test01()
{
    vector<Person>v;
    Person p1("aaa", 10);
    Person p2("bbb", 20);
    Person p3("ccc", 30);
    Person p4("ddd", 40);
    Person p5("eee", 50);
    //向容器中添加数据
    v.push_back(p1);
    v.push_back(p2);
    v.push_back(p3);
    v.push_back(p4);
    v.push_back(p5);
    //遍历容器中的数据
    for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << "姓名:" << (*it).m_name << endl;
        cout << "年龄:" << (*it).m_age << endl;
    }
    //存放自定义数据类型 指针

}
void test02()
{
    vector<Person*>v;
    Person p1("aaa", 10);
    Person p2("bbb", 20);
    Person p3("ccc", 30);
    Person p4("ddd", 40);
    Person p5("eee", 50);
    //向容器中添加数据

    v.push_back(&p1);
    v.push_back(&p2);
    v.push_back(&p3);
    v.push_back(&p4);
    v.push_back(&p5);
    //遍历容器

    for (vector<Person*>::iterator it=v.begin();it!=v.end();it++)
    {
        cout << "姓名:" << (*it)->m_name << "年龄:" << (*it)->m_age << endl;
    }
}
int main()
{
    test02();
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值