C++学习08

一. 模板函数

二.模板类

当一个类中存在通用类型数据,那么他就是模板类

1.模板类语法:

C++
template <class 通用类型名>
class 类名{
    通用类型 成员名;
};
template <class T>
class base
{
    T a;
}  //这就是模板类

  • 模板类在没有实例化之前,不能定义对象!!!
  • 模板类没有自动类型推导功能!! 必须用户手动实例化!!!   <数据类型>

  • 案例:

C++
#include <iostream>
using namespace std;

//模板类
template <class T>
class base{
public:
base(T a) : a(a){}

private:
T a;
};
class base1{
public:
int  a ;

private:
int b;
};

int main(int argc, char const *argv[])
{
    int a = 10086;
    // base a(a);  //定义对象之前 需要先实例化 -- 指定通用类型的数据类型
    base <int>a(a);  //定指定通用类型的数据类型
    return 0;
}

2.模板类和模板函数的区别

  • 模板类没有自动类型推导的功能, 模板函数有
  • 模板类可以使用默认类型 (模板函数其实也有默认类型, 但是一般不用)

C++
#include <iostream>
using namespace std;

//给模板类型设置默认参数
template <class T=int>
class base{
public:
    base(T a) : a(a){}
    void show(){
        cout << this->a << endl;
    }
private:
    T a;

};

int main(int argc, char const *argv[])
{
    //即便设置默认类型 也要写 <>    base <> b(123);
    b.show();

    //当传入的参数与默认类型不匹配
    // 用户可以手动指定类型
    base <string> c("world");
    c.show();
    return 0;
}

3.模板类可以作为函数参数进行传递

注意: 一个模板类, 不能直接通过类名作为函数的参数进行传递

解决方式1 :  指定模板类的参数列表类型

C++
void show(base<int> a){
     cout << a.b << endl;
}

解决方式2 :  继续类型模板化

C++
template <class T>

void show(base<T> a){  //自动类型推导

  cout << a.b << endl;

}

解决方式3 :  模板函数

C++
template <class T>

void show(T a){  //模板函数 -- 对参数进行 自动类型推导

  cout << a.b << endl;

}

总结: 推荐使用第一种方法!!! 更直观, 代码阅读更容易

模板的用途就是为了最终的实例化, --- 实例化后内容就是固定的

注意: 定义完template , 就要直接使用, 如果后面再需要则再次定义

4.模板类成员函数在类外定义

C++
#include <iostream>
using namespace std;

// 定义模板类
template <class T>
class base
{
public:
    //类内声明接口
    base(T a);
    ~base();
    void show();

private:
T a;

};

//类外定义模板类的成员函数
//构造函数
template <class T>
base<T>::base(T a){
    this->a = a;
}

//析构函数
template <class T>
base<T>::~base(){
    cout << "调用析构函数" << endl;
}

//显示接口
template <class T>
void base<T>::show(){
    cout << this->a << endl;
}

int main(int argc, char const *argv[])
{
    base <int> a(10010);
    a.show();
    return 0;
}
//模板类 Person 两个通用类型 T  姓名   T1年龄
// 类外实现接口 : 设置成语数据  显示成员数据  构造函数和析构函数

5.模板类的继承

模板类不能直接被继承

解决方式:

  1. 指定基类的模板类型

//想要被继承
//1 . 指定基类的模板类型
 class son : public base<int>{
};

  1. 派生类继续模板化

template<class T>
class son : public base<T>{
};

练习:

1.模板类 Person  

T(姓名)    A(年龄)

根据Person基类 派生出教师类Teacher

在Teacher 类中初始化Person成员并输出

设计一个通用数组类 可以存储不同的数据类型

三.补充:

c++ 中的数据成员属性

静态属性:

    回顾C语言的静态变量特点:

1.静态全局变量,只能在当前文件中使用

2.修饰局部变量的时候,局部变量只能被初始化一次

3.修饰函数,只能在当前文件中使用

4.静态变量会改变数据的生命周期   (把栈空间的数据改为数据段)

类中的静态成员:

1.类中的静态成员只能在类外初始化

         int base::a=100;  //类外初始化

2.类中的静态成员,不包含在对象空间中,因为静态成员是存储在数据段中的。

       例如: class base{

                        public:

                     static  int a;}   ->大小为 1 。a不在base 的空间中

3.类中的静态成员,可以直接通过 《类名::变量名》 直接调用。 (一定要是公共成员)

4.类中的所有对象,共用静态成员。

类中的静态函数:

1.类中的静态函数,不能使用this 指针, (不是对象空间中的函数)

2.类中的静态函数,不能访问类中的非静态成员数据。

(因为非静态成员数据,要定义对象后才产生空间,因为静态成员函数是先于对象存在的,静态成员函数,就无法访问)

3.静态成员函数是先于对象存在的,所以我们可以 《直接调用共有的静态成员函数》不需要创建对象!

    

//总结:静态成员函数的优点:1.方便用户的调用  2.不需要创建对象直接调用,节省内存空间

设计如下一个文件管理类:

C++
class  file
{
  //构造函数  
    
    
//静态读取文件的内容接口
  
//文件的路径名    
}
//可以实现在不创建 file 对象的情况下,直接读取文件中的内容。

类中的const成员  

回顾c语言中的const 变量:

C++
const int *p; //不能修改,指向的内容

int const *p;//不能修改,指向的内容

int *const p;//不能修改指向的地址

const int *const p;//不能修改指向的内容与地址 ·

找规律: 看*

    如果*和p 一起的,就是内容不可变

    如果是分开的,就地址不可变.

常量成员的作用

作用:提高代码的稳定性与安全性。

const int  a=100;

类中的常量成员

1.类中的常量成员,必须要初始化,否则无法定义对象。 (构造函数中的参数列表初始化,默认值)

2.常量被初始化后无法再次修改     

类中的常量函数:

1.类中的常量函数的定义     const 需要添加在函数的后面

     void show() const  

2.类中的常量函数不能《修改》,类中的《所有》数据成员。  (保护了类中的数据成员,更加安全)

3.假设用户想要数据被常量函数修改,那么就在数据前添加   mutable 关键字即可

常量对象:

1.利用const 修饰的对象就是常量对象     

2.常量对象,无法修改类中的公共成员

3.常量对象,假设想要修改类中的公共成员,那么必须使用  mutable 说明

4.常量对象,只能调用常量函数。无法调用普通函数

练习: 想办法让常量对象可以修改 类中的公共成员。。mutable 修饰即可   

四.C++异常处理(try catch throw)

为什么异常处理???

使用new分配内存时 ,内存空间不够导致无法分配

访问数组元素, 数组下标越界

打开文件,文件不存在

访问指针 , 指针是野指针........................

1 在c语言中,解决异常的方式:

if(fd < 0){

}

利用if语句判断操作是否正确      

2.在C++中处理异常的方式:

try(测试 ) catch(捕获异常) throw (抛出异常)

语法:

C++
try{
    用户要执行的语句
    
}
catch(异常类型){
    异常处理代码
}

3.c和c++中处理异常方式的区别:

c++中的处理异常能力更强, 逻辑上更严谨, 而且系统预定了很多异常的抛出,如new, at等等...

C:面向过程 程序运行->出现错误->解决错误->程序继续执行->出现错写->解决错误->.....

C++: 面向对象 程序的错误是在类中抛出和捕获 不会影响代码的继续执行

程序运行 -> 出现异常1  ->  抛出异常1 -> 程序运行->出现异常2 -> 抛出异常2... -> catch(1){处理}->catch(2){处理}

4.throw 语句:系统不自动抛出异常,需要手动抛出

语法:

C++
throw  表达式;
#include <iostream>
using namespace std;
 

int main(int argc, char const *argv[])
{
    string a = "hello";
    try{
        cout << "12313" << endl;
        int a = 1000;
        if(a >= 100){
            throw "数值过大";  //手动抛出
        }
        cout << "12313" << endl;
    }
    catch(...){
        cout << "出现异常,处理中..." << endl;
    }

    cout << "world" << endl;
    return 0;
}

5.异常的类型捕获:

C++
catch(...)  ...表示捕获任意类型的异常,    拿不到异常的数据
try{
        测试语句
}
catch(int a){

}
catch(base a){

}
catch(string a){

}
catch(...){
        //其他异常
}

6.系统提供的预定义异常类型:

exception类:

C++
catch(exception &e){
        cout << "其他异常:" << e.what() <<endl;
}
 //案例:
 try{
        // int *p = new int[0xFFFFFFFFFF];
        string a = "abcdeg";
        cout << a.at(10000) << endl;
    }
    catch(exception &e){
        cout << "异常原因:" << e.what() << endl;
    }

7.异常的再抛出

当一个函数出现异常的时候, 这个异常如果抛出后未被处理, 会继续抛出, 直到处理为止!!!

C++
#include <iostream>
using namespace std;

 //抛出异常 -- 自己处理
void test(){
    try{
        throw "我是异常";
    }
    catch(...){
        cout << "捕获到异常" << endl;
    }
}

void test1(){  //出现了异常 但是没有处理
     cout << "test1" << endl;
    throw "我是test1的异常";
   
}

void test2(){
    cout << "test2" << endl;
    test1();  //接收到了test1 的 异常
}

 int main(int argc, char const *argv[])
 {
   try{
        test2();
   }
   catch(...){
        cout << "我来处理" << endl;
   }
    return 0;
 }

目录

一. 模板函数

二.模板类

1.模板类语法:

2.模板类和模板函数的区别

3.模板类可以作为函数参数进行传递

4.模板类成员函数在类外定义

5.模板类的继承

三.补充:

c++ 中的数据成员属性

类中的静态成员:

类中的静态函数:

类中的const成员  

常量成员的作用

类中的常量成员

四.C++异常处理(try catch throw)

1 在c语言中,解决异常的方式:

2.在C++中处理异常的方式:

3.c和c++中处理异常方式的区别:

4.throw 语句:系统不自动抛出异常,需要手动抛出

5.异常的类型捕获:

6.系统提供的预定义异常类型:

7.异常的再抛出


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值