C++复习(一)模板

上次学习C++还是好几年以前的事,最近用的一直都是python,cpp除了C以外的用法几乎全忘了。即将开始准备明年2月的暑期实习,打算用C++写算法,所以刷力扣前就先来复习下C++吧。python随意,C++古板,但实际上各有优劣。

简洁易懂的C++教程先过一遍:https://www.runoob.com/cplusplus/cpp-tutorial.html

基础的语法就不在笔记里回顾了,脑子里过一遍for,while,if,int,float,double,int *.... 每个变量都要先声明再使用!别忘记加分号!(Java,Python不需要加)

总结出自己不太熟练的用法,包括:模板、STL、类的继承、指针和C++11新特性,共5部分。

以下笔记参考:https://www.runoob.com/cplusplus/cpp-templates.html

 

C++模板分为两种:函数模板,类模板。为什么需要模板?目的就是一般化、可重复使用!

1.泛型编程(来自百度百科)

泛型可理解为:不与任何特定数据结构或对象类型系在一起。

泛型好处:

(1)编译时的严格类型检查。这是集合框架最重要的特点。

(2)泛型消除了绝大多数的类型转换。如果没有泛型,当你使用集合框架时,你不得不进行类型转换。

关于泛型的理解可以总结下面的一句话,它是把数据类型作为一种参数传递进来。

泛型编程(Generic Programming)最初提出时的动机很简单直接:发明一种语言机制,能够帮助实现一个通用的标准容器库。所谓通用的标准容器库,就是要能够做到,比如用一个List类存放所有可能类型的对象这样的事;泛型编程让你编写完全一般化并可重复使用的算法,其效率与针对某特定数据类型而设计的算法相同。泛型即是指具有在多种数据类型上皆可操作的含义,与模板有些相似。STL巨大,而且可以扩充,它包含很多计算机基本算法和数据结构,而且将算法与数据结构完全分离,其中算法是泛型的,不与任何特定数据结构或对象类型系在一起。

STL是一种泛型编程。面向对象编程关注的是编程的数据方面,而泛型编程关注的是算法。它们之间的共同点是抽象和创建可重用代码,但它们的理念截然不同。

泛型编程最初诞生于C++中,目的是为了实现C++的STL(标准模板库)。其语言支持机制就是模板(Templates)。模板的精神其实很简单:参数化类型。换句话说,把一个原本特定于某个类型的算法或类当中的类型信息抽掉,抽出来做成模板参数T。

2.模板

模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。

模板是创建泛型类或函数的蓝图或公式。库容器,比如迭代器和算法,都是泛型编程的例子,它们都使用了模板的概念。

每个容器都有一个单一的定义,比如 向量,我们可以定义许多不同类型的向量,比如 vector <int> 或 vector <string>

您可以使用模板来定义函数和类,接下来让我们一起来看看如何使用。

函数模板

模板函数定义的一般形式如下所示:

template <typename type> ret-type func-name(parameter list)
{
   // 函数的主体
}

在这里,type 是函数所使用的数据类型的占位符名称。这个名称可以在函数定义中使用。

下面是函数模板的实例,返回两个数中的最大值:

//实例
#include <iostream>
#include <string>
 
using namespace std;
 
template <typename T>
inline T const& Max (T const& a, T const& b) 
{ 
    return a < b ? b:a; 
} 
int main ()
{
 
    int i = 39;
    int j = 20;
    cout << "Max(i, j): " << Max(i, j) << endl; 
 
    double f1 = 13.5; 
    double f2 = 20.7; 
    cout << "Max(f1, f2): " << Max(f1, f2) << endl; 
 
    string s1 = "Hello"; 
    string s2 = "World"; 
    cout << "Max(s1, s2): " << Max(s1, s2) << endl; 
 
   return 0;
}
Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): World

这样,无论待比较的两个数是什么类型float/string/int,都能用这样一种通用的函数进行同样的处理。

查漏补缺:const的神奇用法

T const& a

T可以看做任何一种数据类型,比如int。int const& a,表示变量a是另一个int类型的常量引用

const表示常量,不可修改;&表示引用,内存地址相同;const&表示某种数据类型常量的引用。

int max() const{...}

常函数不对对象的任何成员数据的进行修改(最常见的为打印成员信息的函数),那么我们可以将这个成员函数设置为const函数,以保护对象数据。如void print()const    对成员函数()后加上const限定  如果在该函数里面修改对象的成员数据,则编译器就会报错。const是一种保护措施!

c++ 函数前面和后面 使用const 的作用:

  • 前面使用const 表示返回值为const
  • 后面加 const表示函数不可以修改class的成员,理解为“只读”函数

参考:

https://blog.csdn.net/zha_ojunchen/article/details/82561813

https://blog.csdn.net/qq_32739503/article/details/83341222?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

类模板

正如我们定义函数模板一样,我们也可以定义类模板。泛型类声明的一般形式如下所示:

template <class type> class class-name {
.
.
.
}

在这里,type 是占位符类型名称,可以在类被实例化的时候进行指定。您可以使用一个逗号分隔的列表来定义多个泛型数据类型。

下面的实例定义了类 Stack<>,并实现了泛型方法来对元素进行入栈出栈操作:

#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>
 
using namespace std;
 
template <class T>
class Stack { 
  private: 
    vector<T> elems;     // 元素 
 
  public: 
    void push(T const&);  // 入栈
    void pop();               // 出栈
    T top() const;            // 返回栈顶元素
    bool empty() const{       // 如果为空则返回真。常函数,不可以修改成员变量,否则报错,是一种对数据的保护。
        return elems.empty(); 
    } 
}; 
 
template <class T>
void Stack<T>::push (T const& elem) 
{ 
    // 追加传入元素的副本
    elems.push_back(elem);    
} 
 
template <class T>
void Stack<T>::pop () 
{ 
    if (elems.empty()) { 
        throw out_of_range("Stack<>::pop(): empty stack"); 
    }
    // 删除最后一个元素
    elems.pop_back();         
} 
 
template <class T>
T Stack<T>::top () const 
{ 
    if (elems.empty()) { 
        throw out_of_range("Stack<>::top(): empty stack"); 
    }
    // 返回最后一个元素的副本 
    return elems.back();      
} 
 
int main() 
{ 
    try { 
        Stack<int>         intStack;  // int 类型的栈 
        Stack<string> stringStack;    // string 类型的栈 
 
        // 操作 int 类型的栈 
        intStack.push(7); 
        cout << intStack.top() <<endl; 
 
        // 操作 string 类型的栈 
        stringStack.push("hello"); 
        cout << stringStack.top() << std::endl; 
        stringStack.pop(); 
        stringStack.pop(); 
    } 
    catch (exception const& ex) { 
        cerr << "Exception: " << ex.what() <<endl; 
        return -1;
    } 
}
7
hello
Exception: Stack<>::pop(): empty stack

下一节复习

STL Containers容器

<array>数组

<bitset>位集合

<deque>双端队列

<forward_list>前向链表

<list>链表

<map>映射

<queue>队列

<set>集合

<stack>

<unordered_map>无序映射

<unordered_set>无序集合

<vector>向量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值