1. 前言
模板类是用来生成类的蓝图的。通过一个模板,可以节省大量的代码空间和提高开发的效率,本文章将会就模板类举例进行一个简单的实例。
2. 用模板类实现一个简单的vector
代码目录结构如下:
├── main
│ ├── BUILD
│ ├── main.cc
│ └── myvector.h
└── WORKSPACE
2.1 模板类myvector.h的代码如下
注意: 模板类的定义和声明不建议分离编译,否则可能在编译时会导致链接错误,故myvector的声明和实现都定义在同一个文件当中。
// 文件名:myvector.h
// Copyright [2021] <Copyright Ziliu>
#pragma once
// #include <cmath>
#include <iostream>
#include <memory>
#include <string>
#include <utility>
#include <vector>
// 模板类的声明和定义要放在同一个源文件当中
template <typename T> class MyVector {
public:
// vector的类型
typedef T value_type;
// vector 的 size 的类型
typedef typename std::vector<T>::size_type size_type;
// 构造函数
MyVector();
// 拷贝构造
MyVector(std::initializer_list<T> il);
// Vector中元素的个数
// 通过把类成员函数声明为const以表明它们不修改类对象。
size_type size() const {return data->size();}
bool empty() const {return data->empty();}
// 添加和删除元素
void push_back(const T& t) {data->push_back(t);}
// 当临时值为右值, 使用move可以降低空间代价
void push_bash(T &&t) {data->push_back(std::move(t));}
void pop_back();
// 元素访问
T& back();
T& operator[](size_type i);
private:
std::shared_ptr<std::vector<T>> data;
// 若data[i]无效,则抛出msg
void check(size_type i, const std::string& msg) const;
};
template <typename T>
MyVector<T>::MyVector():data(std::make_shared<std::vector<T>>()) {
}
// 拷贝构造,利用参数il来初始化此vector
template <typename T>
MyVector<T>::MyVector(std::initializer_list<T> il)
:data(std::make_shared<std::vector<T>>(il)) {
}
template <typename T>
void MyVector<T>::pop_back() {
check(0, "pop_back on empty vector.");
data->pop_back();
}
template <typename T>
T& MyVector<T>::back() {
check(0, "back on empty vector.");
return data->back();
}
template <typename T>
T& MyVector<T>::operator[](size_type i) {
check(i, "subscript out of range.");
return (*data)[i];
// return data[i];
}
// 检查输入index对应的位置是否有元素存在
template <typename T>
void MyVector<T>::check(size_type i, const std::string& msg) const {
if (i >= data->size()) {
throw std::out_of_range(msg);
}
}
2.2 main.cc的代码如下
// 文件名: main.cc
// Copyright [2021] <Copyright Ziliu>
#include <cmath>
#include <iostream>
#include "main/myvector.h"
int main() {
MyVector<int> vec;
// push_back
vec.push_back(1);
std::cout << vec[0] << std::endl;
// back
std::cout << vec.back() << std::endl;
// pop_back
vec.pop_back();
std::cout << vec.size() << std::endl;
return 0;
}
2.3 命令行直接编译
g++ main.cc -o test -std=c++17
2.4 bazel的方式编译
// BUILD文件的编写
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
cc_library(
name = "myvector",
hdrs = ["myvector.h"],
)
cc_binary(
name = "main",
srcs = ["main.cc"],
deps = [
"//main:myvector",
],
)