> 文章列表 > C++——从基础到Boost使用

C++——从基础到Boost使用

C++——从基础到Boost使用

目录

一、前言

二、C++ 基础

2.1 源文件

2.2 头文件

2.3 CmakeLists

三、C++ STL

3.1 模板文件

3.2 STL源文件

四、Boost Hello world

五、Boost 常用库使用


一、前言

C++学过很多遍了,不用总是忘,知识基础运用,通过运用可以很快了解如何使用

二、C++ 基础

俗话说得好,空谈误国,实干兴邦,便回顾便实战可以随时验证所学,融会贯通

2.1 源文件

humanbeing.cpp

#include <iostream>
#include "humanbeing.hpp"HUM::Brain::Brain(int sec,int think):m_secret(sec),m_think(think)
{//this 指向当前对象,它是成员函数的一个形参,在调用成员函数时将对象的地址作为实参传递给 thisstd::cout<<"m_secret:"<< m_secret <<std::endl;this->m_cal = this->m_secret+m_think;
}HUM::Brain::~Brain(){float image  =  12.7654321;/*强制类型转换:static_cast 不能用于无关类型之间的转换,如不同的类型指针,数据存储格式不一样const_cast用于去掉 const 和 volatile 修饰reinterpret_cast 高风险,补充static_cast,如具体类型指针转换dynamic_cast 类继承之间类型转换,向上向下均可*/m_think = static_cast<int>(image);std::cout.precision(3);std::cout<<"I'm not gonna think: "<< image <<std::endl;
}int HUM::Brain::add (int a,int b)
{return a+b;
}void HUM::Brain::why(int a ,int b,int c)
{if(this->add(a,b) == c){std::cout<<"you are celver:"<< add(a,b) <<std::endl;}else{std::cerr<<"you are stupid:"<< add(a,b) << std::endl;}
}
/*引用*/
void HUM::Brain::swap(int &a, int &b)
{std::cout<<"before a:"<< a <<" b:" << b << std::endl;int tem = b;b = a;a = tem;
}
void HUM::Brain::pstrTrans(Brain* &pbr)
{std::cout<<"&引用传指针* m_think:"<< pbr->m_think << std::endl;
}/*const 在前修饰返回值,在后修饰成员函数针对成员变量; const对象只能访问const成员;*/
int HUM::Brain::getMySecret() const
{std::cout<<"my secret: "<< m_secret << std::endl;return this->m_secret;
}void HUM::Brain::staticThinking()
{std::cout<<"I need "<< HUM::Brain::ms_area <<" hours to thinking"<< std::endl;
}//友元
void HUM::freeFunc(Brain* pBrn)
{std::cout<<"I'm your friend,your sceret is "<<pBrn->m_secret<<std::endl;
}void HUM::Brain::introduceFriends(Animal* pani)
{std::cout<<"My friends have legs "<<pani->m_leg <<std::endl;
}void  HUM::Brain::getFriendsDetail(Animal* pani)
{std::cout<<"My friends have child "<<pani->m_children <<std::endl;
}

male.cpp

#include "male.hpp"
#include <iostream>HUM::Male::Male(int sec,int think,int age):Brain(sec,think),m_age(age)
{std::cout<<" Male 类 构造"<<std::endl;
}

nature.cpp

#include <iostream>
#include "nature.hpp"HUM::Animal::Animal(int legs):m_leg(legs)
{m_children = 3;std::cout<<"the animal have legs " <<m_leg<<std::endl;
}

main.cpp

#include <iostream>
#include "humanbeing.hpp"
#include "nature.hpp"
#include "male.hpp"
#include <typeinfo>
int HUM::Brain::ms_area = 5;int main(int argc,char*argv[]){int a = 6;int b = 2;char sumAB = 13;HUM::Brain *phb  = new HUM::Brain(3,4);std::cout<<"input a number:"<<std::endl;//std::cin.getline(&sumAB,5);std::cout<<"the a number is:"<< static_cast<int>(sumAB) <<std::endl;phb->why(phb->ms_area,7,static_cast<int>(sumAB));std::cout<<"think: "<<phb->m_think<<std::endl;std::cout<<"a+b = "<<phb->add(a,b)<<std::endl;phb->why(a,b);phb->swap(a,b);//引用phb->pstrTrans(phb);std::cout<<"after a:"<< a <<" b:" << b << std::endl;phb->getMySecret();HUM::Brain::staticThinking();//友元HUM::freeFunc(phb);HUM::Animal dog(7);phb->introduceFriends(&dog);phb->getFriendsDetail(&dog);delete phb;//继承int age = 18;HUM::Male boy(a,b,age);boy.Brain::getMySecret();//子类访问基类的方法//typeid使用方法//获取一个字面量的类型信息const type_info& dInfo = typeid(25.65);std::cout << dInfo.name() << " | " << dInfo.raw_name() << " | " << dInfo.hash_code() << std::endl;//流//输出单个字符,ASCII码 putstd::cout.put(71).put(79).put(79).put(68).put('\\n');//向输出缓冲区添加指定字符串 writestd::cout.write("http://", 7).write("c.biancheng.net", 15).write("/cplus/", 7).write("\\r\\n",4);//tellp seekp 读取或修改位于输出缓冲区的数据return 0;
}

2.2 头文件

humanbeing,hpp

#ifndef HUMANBEING
#define HUMANBEING 1
#include "nature.hpp"
class Animal;
namespace HUM{class Brain{//默认成员都是private, struct默认是publicpublic:/*都可以访问*/int m_think;int m_cal;int m_rat;public:/*静态变量:实现多个对象共享数据的目标,类或者对象访问*/static int ms_area;private:/*成员函数中访问,子类、类外不能访问*/int m_secret;protected:/*子类、成员函数都可以访问,类外无法访问*/int m_littleBrain;public:Brain(int sec,int think);~Brain();int add (int a,int b);/*类内的成员函数可以相互调用,访问*/void why(int a ,int b,int c = 8);void swap(int &a, int &b);/*引用传参: 数据别名*/void pstrTrans(Brain* &pbr);/*引用传递对象指针类型*//*int& q[10] ;//q首先向右结合,所以这个相当于 (int&)q[] q是个数组,其中的元素是引用,叫引用的数组int(&p)[10] ;p首先和&结合,所以p是引用,引用的对象是数组,叫作数组的引用*/public:int getMySecret() const;/*const 修饰成员函数,不能改变成员的值*/public: /*静态成员函数只能访问静态成员(没有this指针),类直接调用*/   static void staticThinking();public:/*友元函数可以独立,也可以是其他类成员函数,友元函数可以访问类所有成员*/friend void freeFunc(Brain* pBrn);/*两个文件的友元函数要相互添加.hpp文件*/void introduceFriends(Animal* pani);void getFriendsDetail(Animal* pani);};void freeFunc(Brain* pBrn);
}
#endif

male.hpp

#ifndef MALE
#define MALE 1
#include "humanbeing.hpp"namespace HUM{class Male : public Brain{public:int m_age;int m_height;int m_weight;using Brain::m_littleBrain;//protected 权限改为 publicpublic:/*对任意一个类,默认的构造函数,拷贝构造函数,析构函数如下:1 A(void); // 缺省的无参数构造函数// 缺省的拷贝构造函数,只有单个形参,形参为对本类类型对象的引用(用const修饰)//拷贝是在 【初始化】 阶段(类A a2 = a1)进行的,非初始化阶段赋值调用重载运算符=//也就是用其它对象的数据来初始化新对象的内存,针对有指针类型变量的类2 A(const A &a);3 ~A(void); // 缺省的析构函数4 A & operate =(const A &a); // 缺省的赋值函数*/Male(int sec,int think,int age);/*派生类如果有与基类同名的函数,则回覆盖基类的函数,使用自己的函数*//*虚继承可以解决菱形问题A->B , A-> C  , B C ->D, 比如iostream 是从istream 和ostream继承得来,它俩从base_ios继承* 虚继承可以保留一份虚基类的成员,不回产生二义性。* 强制类型转换,遵循向上转型,转型后只能访问基类继承的成员*//*虚函数:基类指针只能访问派生类成员变量,不能访问派生类成员函数* 基类指针指向基类就访问基类成员,指向派生类就访问派生类,现象叫多态*//*纯虚函数:virtual 返回值类型 函数名 (函数参数) = 0;* 纯虚函数的类叫抽象类,抽象类是类型,让派生类实现纯虚函数*/};
}#endif

nature.hpp

#ifndef NATURE
#define NATURE 1
#include "humanbeing.hpp"
namespace HUM{class Animal{public:int m_leg;public:friend class Brain;//友元类private:int m_children;public:Animal(int legs);friend void introduceFriends(Animal* pani);//友元函数};}
#endif

2.3 CmakeLists

cmake_minimum_required(VERSION 3.0)project(reviewcppVERSION 1.0DESCRIPTION "know how to use cmake"#LANGUAGES CXX #指定编程语言为CPP, 默认是CXX C
)#add
aux_source_directory(./src SRC_DIR)
include_directories(./inc)
#exe
add_executable(cpprun ${SRC_DIR})

三、C++ STL

stand template library标准模板库通过模板实现了常用的数据结构算法,做到了算法和数据结构的分离。vector 的底层为顺序表(数组),list 的底层为双向链表,deque 的底层为循环队列,set 的底层为红黑树,hash_set 的底层为哈希表

3.1 模板文件

tempt.hpp中定义

#ifndef TMPT
#define TMPT
//函数模板
/*
template <class 形参名,class 形参名,......> 返回类型 函数名(参数列表)
{函数体
}
template <class T> void swap(T& a, T& b){},
*/
//类模板
/*
template<class  形参名,class 形参名,…>   class 类名
{ ... };
template<class T> class A{public: T a; T b; T hy(T c, T &d);};
template<class T1,class T2> void A<T1,T2>::h(){};
*/
template<class T> 
class Aba{public:T g(T a,T b);Aba();
};#endif

3.2 STL源文件

/*
迭代器(指针):运用泛型技术隐藏不同容器内部差异,实现统一接口传送数据,遍历读写数据
输入迭代器,输出迭代器,前向迭代器fd,双向迭代器dd,随机访问迭代器rd
stack和queue不支持迭代器
容器类名::iterator 迭代器名; 常量正向迭代器const_iterator,反向迭代器 reverse_itertor,常量反向迭代器const_reverse_iterator
*/
/*
序列容器:
array ,长度固定不变
vector(rd),长度可变,尾部增加或删除元素效率高
deque(rd),支持高效尾部头部增加删除元素
list(dd),可变,任何地方增加删除元素高效,访问元素比前3个慢
forward_list, 正向链表,类似list,访问只能从第一个开始,比list块、节省内存
关联容器<key,value>:排序容器(从小到大)set(dd),multiset,map(dd),multimap;快速查找、读取删除,插入元素效率高于序列容器
哈希容器unordered_set(fd),unordered_multiset(fd),unordered_map(fd),unordered_multimap(fd)
*/
#include <iostream>
#include <array>
#include <vector>
#include <map>
#include "tmpt.hpp"
#include <deque>
#include <list>
#include <forward_list>
#include <iterator>
#include <utility>
#include <string>
#include <map>
#include <functional> //std::greater ,std::less
#include <set>
#include <unordered_map>
#include <stack>
#include <queue>//priority_queue
#include <algorithm>
#include <unordered_set>
using uint_t = unsigned int;
using map_int_t  = std::map<std::string,int>;
using func_t = void(*)(int,int); //typedef void(*func_t)(int,int)template<class T> class A{public:T g(T a,T b){return a+b;}A(){std::cout<< "tem a out" <<std::endl;}
};
//tmpt.hpp
template<class T> Aba<T>::Aba(){std::cout<< "tem a out" <<std::endl;}template<class T> T Aba<T>::g(T a,T b)
{return a+b;
}class CopyReg{public:bool operator()(const int& i){return(i%2==1);}
};int main(int argc,char* argv[])
{//templateAba<int> a;std::cout<< "template call:"<<a.g(2,3) <<std::endl;int i = 0;//----------- array -------------------std::array<double,10> box;//不能用push_back//std::array<double,10>::iterator ibox;for(auto ibox = box.begin();ibox!=box.end();ibox++,i++){box[i] = i;//std::cout<<box.at(i)<<std::endl;//box[i]//std::cout<< *ibox <<std::endl;box.at(i)+=3;//at避免越界访问}for(auto& v :box )//每一个元素的引用{v = v+1;//std::cout<< "v: "<< v <<std::endl;}box.fill(7.7);//填充所有元素std::cout<<"box back: "<<box.back()<<std::endl;//frontstd::cout<<"box length: "<<box.size()<<std::endl;auto first_it = box.begin();auto last_it = box.end();while(first_it !=last_it){*first_it = i;//std::cout<< *first_it <<std::endl;++first_it;i++;}//----------- vector -------------------std::vector<uint_t> vec(10,0);std::vector<uint_t> vct;for(auto i = 0;i<5;i++)vct.push_back(i);//从队尾追加,先创建再拷贝或移动到容器中for(auto i = 0;i<5;i++)vct.emplace_back(i);//从队尾追加,直接在容器尾部创建元素,优先使用emplace_back//删除vct.pop_back();//队尾删除vct.erase(vct.begin()+3);std::cout<<"befor :"<<vct.capacity()<<std::endl;vct.shrink_to_fit();//将内存减少到等于当前元素实际所使用大小std::cout<<"after :"<<vct.capacity()<<std::endl;std::swap(vec,vct);vec.at(2) = 77;//支持防止越界访问atvec.insert(vec.begin()+2,3);//第一个参数是迭代器,insert支持插入容器和多个元素vec.emplace(vec.end()-2,7);//emplace只允许一次插入一个元素,而不是多个for(auto &v : vec)//每个元素引用{v+=2;//std::cout<< "v:vec "<<v<<std::endl;}std::cout<< "vec:front "<<vec.front()<<std::endl;//队头, back()队尾vec.clear();vct.clear();//移出所有元素,大小为0//----------- deque -------------------double ended queue: 不保证所有元素存储连续空间中;remove所有相等元素std::array<int,5> ar{1,2,3,4,5};std::deque<int> dq(ar.begin()+2,ar.end());dq.pop_back();dq.pop_front();dq.push_back(7);dq.push_front(8);for(auto& d: dq){//std::cout<< "d:dq "<< d <<std::endl;}dq.clear();//----------- list  -------------------双向列表,两端可以快速删除插入,访问元素慢/*remove_if:删除满足条件的元素unique:删除相邻重复元素,只保留一个merge:合并已排序list容器sort:排序(默认从小到大)*/std::list<int> vlist(3,6);vlist.push_back(7);for(std::list<int>::iterator it = vlist.begin();it !=vlist.end();it++){//std::cout<< "L:list "<< *it <<std::endl;}vlist.clear();//----------- forward list -------------------高效的list,前向链表,不提供size()std::forward_list<int> vFL(3);vFL.push_front(1);vFL.push_front(11);vFL.push_front(111);int vfsize = std::distance(std::begin(vFL),std::end(vFL));std::cout<< "FL:list size "<< vfsize <<std::endl;auto it = vFL.begin();advance(it, 1);//移动迭代器while (it!=vFL.end()){std::cout << *it << " ";++it;}vFL.clear();//----------- pair-------------------#include <utility> 键值对,<first, second>//make_pair返回一个pair对象,是一个临时对象,右值引用 调用移动构造函数std::pair <std::string, std::string> pair1(std::make_pair("C++", "http://c.biancheng.net/cplus/"));std::pair<std::string,std::string>   pair2 = std::make_pair("C++", "hello world");std::cout << "pair2: " << pair2.first << " " << pair2.second << std::endl;//----------- map-------------------/*键是唯一的;根据键大小进行排序,默认std::less<T>;设置为std::greater<T>map的元素是pair类对象;lower_bound(key)不小于key的键值对迭代器upper_bound(key)大于key的键值对迭代器*/std::map<std::string, int,std::greater<std::string> > myMap;myMap.emplace("job1",8500);myMap.emplace("job2",20000);myMap.emplace("job3",16000);if(!myMap.empty()){for(auto it = myMap.begin();it != myMap.end();it++){std::cout<<it->first<<" "<<it->second<<std::endl;}}// multimap 键可以重复//----------- set -------------------/*键值完全相同,值不能重复,根据键大小进行排序修改元素的方法,先删除,再添加*/std::set<std::string> myset{"http://c.biancheng.net/java/","http://c.biancheng.net/stl/"};myset.insert("http://c.biancheng.net/python/");for(auto it = myset.begin();it!=myset.end();it++)std::cout<< *it <<std::endl;//multiset 值可以重复//----------- unordered_map -------------------/*无序容器内部存储的键值对是无序的,各键值对的存储位置取决于该键值对中的键无序容器擅长通过指定键查找对应的值,不擅长遍历容器不会对键值对排序*/std::unordered_map<std::string, std::string> my_uMap{{"C","http"} };auto itP2 = my_uMap.insert(pair2);//查找指定键对应的值,效率比关联式容器高std::string str = my_uMap.at("C");std::cout << "str = " << str << std::endl;//----------- 容器适配器 -------------------/*将不适用的转化为可用stack栈适配器:默认deque,满足条件vector,deque,list;单端口容器(栈顶),先进后出,push,pop,top,sizequeue队列适配器:默认deque,满足条件deque,listpriority_queue优先权队列适配器:默认vector,满足条件vector,deque, First In Largest Out*/std::list<int> temL{1,2,3};std::stack<int,std::list<int>> myStack(temL);while(!myStack.empty()){//std::cout<<myStack.top()<<std::endl;myStack.pop();}std::array<int,4> temA{ 4,1,3,2 };std::priority_queue<int>myPQ(temA.begin(),temA.end());//{4,2,3,1}while(!myPQ.empty()){std::cout << myPQ.top()<<" ";myPQ.pop();//移除队头元素的同时,将剩余元素中优先级最大的移至队头}//----------- 迭代器适配器 -------------------/*reverse_iterator:逆向迭代器 ++ --, 反向迭代器内部互换了 ++ 和 -- insert_iterator:在容器任何位置添加新的元素istream_iterator:用于从文件或者键盘读取数据move_iterator:将某个范围的类对象移动到目标范围,而不需要通过拷贝移动*/std::reverse_iterator<std::list<int>::iterator> rb = temL.rbegin();std::reverse_iterator<std::list<int>::iterator> re = temL.rend();while (rb != re) {std::cout << *rb << " ";++rb;}//----------- 常用算法 -------------------/*http://c.biancheng.net/view/7493.htmlfind_if:在容器中查找满足条件的元素迭代器索引search:在序列 A 中查找序列 B 第一次出现的位置binary_search:查找指定区域内是否包含某个目标元素,二分法copy_if:过滤器unique:可以在序列中原地移除重复的元素,常和std::erase搭配rotate:如何旋转序列transform:将函数应用到序列的元素上,并将这个函数返回的值保存到另一个序列中replace:用新的值来替换和给定值相匹配的元素*/std::vector<int> vecG{4,2,3,1,5};std::vector<int>::iterator vit = std::find_if(vecG.begin(),vecG.end(),CopyReg());std::cout << "find_if: "<<*vit << std::endl;std::vector<std::string> names {"A1", "Beth", "Carol", "Dan", "Eve","Fred", "George", "Harry", "Iain", "Joe"};std::unordered_set<std::string> more_names {"Jean", "John"};size_t max_length{4};std::copy_if(std::begin(names), std::end(names), std::inserter(more_names, std::begin(more_names)),[max_length](const std::string& s) { return s.length() <= max_length;});return 0;
}

CMakeLists.txt与第二节使用的相同

四、Boost Hello world

五、Boost 常用库使用