C++学习笔记3--一些应用

【模板】

函数模板定义的一般形式:

template <类型形式参数表>

返回类型 函数名(形式参数表)
{
    ...     //函数体
}

范例:

定义一个求和的函数模板

template <class type>
type Sum(type xvar, type yvar) {
    return xvar + yvar;
}

在定义完函数模板后,需要在程序中调用函数模板。下面的代码演示了Sum函数模板的调用。

int iRet = Sum(10, 20);

int dRet = Sum(1.2, 3.45);

消除模板调用产生歧义的方法-->在调用函数模板时显示标识模板类型。如:

int iRet = Sum(10.5, 20);

double dret = Sum<double>(10, 20.5);

用函数模板生成实际可执行的函数又称为模板函数。

例:使用数组作为模板参数

#include <iostream>
using namespace std;
template <class type,int len>   //定义一个模板类型
type Max(type array[len]) {     //定义函数模板
    type ret = array[0];
    for(int i=1;i<len;i++) {
        ret = ret > array[i] ? ret : array[i];
    }
    return ret;
}
int main(int argc,char* argv[]) {
    int array[5] = {1,2,3,4,5}; //定义一个整型数组
    int iret = Max<int,5>(array);   //调用函数模板Max
    double dset[3] = {1.2, 3.45, 6.789}; //定义实数数组
    double dret = Max<double,3>(dset);  //调用函数模板Max
    cout << dret << endl;
    return 0;
}

重载函数模板举例:

#include <iostream>
#include <cstring>
using namespace std;
template<class type>
type Min(type a, type b) { //定义函数模板
    return a < b ? a : b;
}
char* Min(char* a, char* b) { //重载函数模板
    if(strcmp(a, b) < 0) return a;
    return b;
}
int main(int argc, char* argv[]) {
    cout << Min(10, 3) << endl;
    cout << Min('a','b') << endl;
    cout << Min("lasolmi","hello world") << endl;
    return 0;
}

类模板的定义形式:

template<类型形式参数表>

class 类模板名

{

... //类模板体

};

类模板成员函数的定义形式:

template<类型形式参数表>

返回类型 类模板名 <类型名表>::成员函数名(形式参数列表)

{

... //函数体

}

生成类的形式如下:

类模板名<类型实在参数表>

用新生成的类定义对象的形式如下:

类模板名<类型实在参数表> 对象名

在类模板定义中,类型形式参数表中的参数也可以是其他类模板。例如:

template<template<class A> class B>
class CBase {
private:
    B<int> m_n;
};

类模板也可以进行继承。例如:

t

emplate<class T>
class CDerived : public T
{
public:
    CDrived();
};
template<class T>
CDerived<T>::CDerived(): T() {
    cout << :: <<endl;
}
int main(int argc,char* argv[]) {
    CDerived<CBase1> D1;
    return 0;
}

例:简单类模板

#include <iostream>
using namespace std;
template<class T1, class T2>
class MyTemplate {
    T1 t1;
    T2 t2;
public:
    MyTemplate(T1 tt1, T2 tt2) {t1 = tt1; t2 = tt2;}
    void display() {cout << t1 << " " << t2 <<endl;}
};
int main(int argc, char* argv[]) {
    int a = 123;
    double b = 3.14159;
    MyTemplate<int,double> mt(a, b);
    mt.display();
    return 0;
}

默认模板参数,例:

template<class T1, class T2=int>

为具体了女性的参数提供默认值,例:

template<class T1, class T2, int num=10>

有界数组模板:

#icnlude <cassert>
template<class T, int b>
class Array {
    T& operator[] (int sub) {
        return sub >=0 && sub < b;
    }
};

模板的定制:定义完模板后如果想扩展模板新类的功能,需要对类模板进行覆盖,是模板类能

够完成功能。覆盖操作可以针对整个类模板、部分类模板以及类模板的成员函数。这种覆盖操

作成为定制。

对于同一类型的模板实例,其静态数据成员是共享的。

【STL标准模板库】

序列容器:

向量类模板

双端队列类模板

链表类模板

结合容器

set类模板

multiset类模板

map类模板

multimap类模板

算法

非修正序列算法

修正序列算法

排序算法

数值算法

迭代器

输出迭代器

输入迭代器

前向迭代器

双向迭代器

随机访问迭代器

【RTTI与异常处理】

运行是类型识别(Run-time Type Identification, RTTI)是在只有一个指向基类的指针或引用

时确定的一个对象的类型。

范例:CBint类和CBString类都继承与CBase类,这3个类存在一个公共方法GetName(),而CBint

类有自己的特有方法GetInt(),CBString类有自己的特有方法GetString()。如果想通过CBase

类的指针调用CBint类或CSString类的特有方法时就必须确定指针的具体类。字啊面的代码完成

了这样的功能。

#include <cstdio>
class CBase {   //基类
public:
    virtual char * GetName() = 0;   //虚方法
};
class CBint : public CBase {
public:
    char * GetName() {return "CBint";}
    int GetInt() {return 1;}
};
class CBString : public CBase {
public:
    char * GetName() {return "CBString";}
    char * GetString() {return "Hello";}
};
int main(int argc, char* argv[]) {
    CBase* B1 = (CBase*)new CBint();
    printf(B1->GetName());
    CBint* B2 = static_cast<CBint*>(B1);    //静态替换
    if(B2) printf("%d" , B2->GetInt());
    CBase* C1 = (CBase*)new CBString();
    printf(C1->GetName());
    CBString* C2 = static_cast<CBString*>(C1);
    if(C2) printf(C2->GetString());
    return 0;
}

从上面代码可以看出基类CBase的指针B1和C1分别指向了CBint类与CBString类的对象,并且在

程序运行时基类通过static_cast进行了转换,这样就形成了一个运行时类型是别的过程。

RTTI与引用

#include <typeinfo>

typeid(p); //p是某类型指针

typeid()获取的指针是基类类型,而不是子类类型或派生类类型,typeid()获取的引用是子类

类型。

【RTTI映射语法】

dynamic_cast:用于安全类型的向下映射。

例如,通过dynamic_cast实现基类指针的向下转型。

const_cast:用于映射常量和变量。

例如,在常方法中修改成员变量和常量的值。

static_cast:为了行为良好和行为较好使用的映射,如向上转型和类型自动转换。

例如,通过static_cast将子类指针向上转成基类指针。

reinterpret_cast:将某一类型映射回原有类型时使用。

例如,将整型转成字符型,再由reinterpret_cast转换回原类型。

【异常处理】

抛出异常:

例:将错误ID和错误信息以类对象的形式进行异常抛出。

#include <iostream>
#include <cstring>
using namespace std;
class CCustomError {
private:
    int m_ErrorID;
    char m_Error[255];
public:
    CCustomError(int ErrorID, char* Error) {
        m_ErrorID = ErrorID;
        strcpy(m_Error, Error);
    }
    int GetErrorID() {return m_ErrorID;}
    char* GetError() {return m_Error;}
};
int main(int argc, char* argv[]) {
    try {
        throw (new CCustomError(1,"出现异常!"));
    } catch(CCustomError* error) {
        //输出异常信息
        cout << "异常ID:" << error->GetErrorID() <<endl;
        cout << "异常信息:" << error->GetError() << endl;
    }
    return 0;
}

异常捕获:

异常抛出信号发出后,一旦被异常处理器接收到就被销毁。异常处理器应具备接受任何异常的

能力。异常处理器紧随try块之后,处理的方法由关键字catch引导。

有时并不一定在列出的异常处理中包含所有可能发生的异常类型,所以C++提供了可以处理任何

类型异常的方法,就是在catch后面的括号内添加“...”代码如下:

int main(int argc, char* argv[]) {
    try {
        throw "字符串异常";
    } catch (CCustomError* error) {
        //输出异常信息
        cout << "异常ID:" << error->GetErrorID() <<endl;
        cout << "异常信息:" << error->GetError() << endl;
    } catch (char* error) {
        cout << "异常信息:" << error << endl;
    } catch (...) {
        cout << "未知异常信息" << endl;
    }
    return 0;
}

异常匹配:

能匹配到基类,而不能匹配到其派生类。

为了正确的进入指定的异常处理器,在对异常处理器进行排列时应将派生类排在前面,而将基

类排在后面。

标准异常:

下面给出了C++提供的一些标准异常:

namespace std
{
    //exception 派生
    class logic_error;
    //logic_error 派生
    class domain_error;
    class invalid_argument;
    class length_error;
    class out_of_range;
    class bad_cast;
    class bad_typeid;
    //exception 派生
    class runtime_error;
    //runtime_errot 派生
    class range_error;
    class overflow_error;
    class bad_alloc;
}

【程序调试】

程序错误常见的4种类型:语法错误、连接错误、运行时错误 和 逻辑错误。

时间: 2024-10-13 01:26:51

C++学习笔记3--一些应用的相关文章

vector 学习笔记

vector 使用练习: /**************************************** * File Name: vector.cpp * Author: sky0917 * Created Time: 2014年04月27日 11:07:33 ****************************************/ #include <iostream> #include <vector> using namespace std; int main

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则 用了几天时间看了一下开源框架Caliburn.Micro 这是他源码的地址http://caliburnmicro.codeplex.com/ 文档也写的很详细,自己在看它的文档和代码时写了一些demo和笔记,还有它实现的原理记录一下 学习Caliburn.Micro要有MEF和MVVM的基础 先说一下他的命名规则和引导类 以后我会把Caliburn.Micro的 Actions IResult,IHandle ICondu

jQuery学习笔记(一):入门

jQuery学习笔记(一):入门 一.JQuery是什么 JQuery是什么?始终是萦绕在我心中的一个问题: 借鉴网上同学们的总结,可以从以下几个方面观察. 不使用JQuery时获取DOM文本的操作如下: 1 document.getElementById('info').value = 'Hello World!'; 使用JQuery时获取DOM文本操作如下: 1 $('#info').val('Hello World!'); 嗯,可以看出,使用JQuery的优势之一是可以使代码更加简练,使开

[原创]java WEB学习笔记93:Hibernate学习之路---Hibernate 缓存介绍,缓存级别,使用二级缓存的情况,二级缓存的架构集合缓存,二级缓存的并发策略,实现步骤,集合缓存,查询缓存,时间戳缓存

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

Activiti 学习笔记记录(三)

上一篇:Activiti 学习笔记记录(二) 导读:上一篇学习了bpmn 画图的常用图形标记.那如何用它们组成一个可用文件呢? 我们知道 bpmn 其实是一个xml 文件

HTML&CSS基础学习笔记8-预格式文本

<pre>标签的主要作用是预格式化文本.被包围在 pre 标签中的文本通常会保留空格和换行符.而文本也会呈现为等宽字体. <pre>标签的一个常见应用就是用来表示计算机的源代码.当然你也可以在你需要在网页中预显示格式时使用它. 会使你的文本换行的标签(例如<h>.<p>)绝不能包含在 <pre> 所定义的块里.尽管有些浏览器会把段落结束标签解释为简单地换行,但是这种行为在所有浏览器上并不都是一样的. 更多学习内容,就在码芽网http://www.

java/android 设计模式学习笔记(14)---外观模式

这篇博客来介绍外观模式(Facade Pattern),外观模式也称为门面模式,它在开发过程中运用频率非常高,尤其是第三方 SDK 基本很大概率都会使用外观模式.通过一个外观类使得整个子系统只有一个统一的高层的接口,这样能够降低用户的使用成本,也对用户屏蔽了很多实现细节.当然,在我们的开发过程中,外观模式也是我们封装 API 的常用手段,例如网络模块.ImageLoader 模块等.其实我们在开发过程中可能已经使用过很多次外观模式,只是没有从理论层面去了解它. 转载请注明出处:http://bl

[原创]java WEB学习笔记48:其他的Servlet 监听器:域对象中属性的变更的事件监听器 (3 个),感知 Session 绑定的事件监听器(2个)

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------

java/android 设计模式学习笔记(10)---建造者模式

这篇博客我们来介绍一下建造者模式(Builder Pattern),建造者模式又被称为生成器模式,是创造性模式之一,与工厂方法模式和抽象工厂模式不同,后两者的目的是为了实现多态性,而 Builder 模式的目的则是为了将对象的构建与展示分离.Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程.一个复杂的对象有大量的组成部分,比如汽车它有车轮.方向盘.发动机.以及各种各样的小零件,要将这些部件装配成一辆汽车,这个装配过

[原创]java WEB学习笔记12:一个简单的serlet连接数据库实验

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------