对于 C++知识点 的总结

开发环境

  1. 使用MFC或WPF

  2. 使用跨平台的QT

  3. 使用图形库OpenGL

  4. EasyX 头文件 #include<graphics.h>

    基础操作

    1. 设置背景颜色 setbkcolor(RBG( , , ,))

    ​ R=红色 G=绿色 B=黑色

    1. initgraph( , ) 初始化图形界面

    2. 设置画笔样式 : setlinestyle(PS_SOLID,10); <实线,10(宽度)>

    3. 设置字体颜色 :settextcolor(RBG());

    4. 设置字体样式 :settextstyle(高度(像素),0(不指定宽度),”微软雅黑“(字体名称))

    5. 在指定位置输出文本: outtextxy(170,190,“无码”);

      在坐标(170,190)的位置打印出无码

    6. 画线:line(180,380,460,100); 在两个端点之间画

    7. 输出文本drawtext(“内容”,&rec,DT_CENTER(水平居中)|DT_VCENTER(垂直居中)|DT_SINGLEINE(单行))

    8. 解决初始化界面图片出现闪烁的问题

      • beingBatchDraw();

        加载图片

        EndBatchDaraw();

图像处理

  • 加载图片loadimage(0,“bj.jpg”); 前一个参数为0,可直接加载到界面

  • 画方框:rectangle(左上角坐标,右下角坐标)

  • 使用背景音乐

    需包含 #pragma comment(lib,“winmm.lib”) <告诉编译器,加载winmm.lib 库头文件>

    #include<mmsystem.h> //mci 库文件(播放音乐头文件)

    Deom: micsendstring(“play 极乐净土.MP3 repeat”,0,0,0); repeat 循环播放

  • IMAGE; //图片类

  • putimage(0,0,images[i]); //从左上角输入图片

语法部分

  • unsigned 无符号型

  • 16进制 ox做前缀

  • 8进制 o做前缀

    • 清空输入缓冲区 cin*.*sync(); VS2015以上版本无效

    • string addr ; addr*.*empty() ; “判断字符串是否为空,返回值 true 、false”

    • fflush(stdio); C语言 清空输入缓冲区

    • 更加强大的清空缓冲区方式

      1.cin.clear();        //清除错误标记
      2.cin.ignore(10,‘1’);      //遇到‘1’为止,包含‘1’      10是最多清楚多少个数据
      
      ios流的最大值:std::numeric_limits<streamsize>::max()
      
  • sprintf: 把指定的信息打印到字符串

    demo: sprintf(fileName,“年龄%d”,age); fileName是字符串数组

  • Sleep() //延时 (毫秒)

  • 命令提示窗口(改变)

    deom: mode con cols(窗口 宽)=40 lines(高)=5

  • C++字符串转C语言字符串 char strl[]; strl.c_str();

  • inline 表示内联函数 inline int add(int a, int b);

(C++流)文件流

​ Demo:

​ #include //包含头文件

​ string fileName;

​ ifstream file; // 读文件

​ cin>>fileName;

​ file.open(fileName);

​ file>>name>>age; //从文件中读取

  1. if(file.fail()){

    ​ cerr<<“打开文件出错”<<strerror(errno)<<endl;

    //错误原因保存到(errno)

    }

    • if(file.eof()) //如果读取到文件尾部 eof文件末尾指示器
  2. ifstream 对文件输入(读文件)

  3. ofstream 对文件输入(写文件)

  4. fstream 对文件输入或者输出

  5. 读写文件格式 : ios:binary (二进制的方式)

  6. ios::out|ios::binary (以二进制的方式写入文件)

  7. 使用文件流对象 write 方法写入二进制数据, read 方法读取二进制数据

    • write(char *buffer(起始位置),int count(大小) );
  8. 格式化读写文件:

    `

    ​ stringstraeam s;

    ​ s<<“姓名:”<<name;

    ​ outfile<<s.str(); //outfile 是文件对象

    ​ string line;

    ​ getline(infile,line); //一行读取

    `

  9. 文件状态检查:

`

file.is_open(); //判断文件是否打开成功

file.eof(); //流file 是否结束

s.clear(); //流S的所有状态都被复位


`

  1. 文件流的定位:

    • .seekg(off_type offset(偏移量), ios::seekdir origin(起始位置));

    ​ 设置输入流文件的位置

    • .beg (相对于开始位置) .cur (相对于当前位置) .end (相对于结束位置)

    • .tellg //返回该输入流的当前位置(距离文件起始位置的偏移量)

      ·

      ​ s.seekg(0,s.end);

      ​ return s.tellg();

      ·

    • .seekp //设置该输入流的位置

      ·

      ​ s.seekp(4,s.beg);

      ·

  2. 设置输入格式:

    #include<iomanip>      //包含头文件
    set(3)<<setiosflags(left)          //left左对齐       //控制输出格式(对齐用)
    3  表示输出的宽度
    

指针

  1. 指针数组 int *k[2];

  2. 指针强制内型转换

    Deom: int arr[]={1,2,3};

    void *p=arr;

    char *p1=(char *)p;

​ 3.函数指针: 定义int compare_int (void *a,void *b){…}

Demo:

int compare_int(void *,void *); //可以不这样写 void *a

int (*p)(void * ,void *); //把函数名改成( *函数指针名)

fp=&compara_int ; //进行赋值

( *fp)(&x,&y); //或者fp(&x,&y);

​ 4.指针的引用:int *p=&x;

  • 定义:int *&q=p;

创建头文件(库头文件)

  • #ifndef _TOOL_H(头文件名 tool.h)

    #define _TOOL_H

    #endif

动态内存分配

  • Dmeo:

    int *salary=NULL;

    salary=new int[num]; //类型是int 分配数量num个的 salary

    释放: delete[] salary;

    1. salary =new int (1) //只分配一个int大小的空间,并赋初值为1

内存拷贝函数

  • 从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置。

    void *memcpy(void *dest,const void *src,size_t n);

    变量存储类型

  • extern 把全局变量在其他的源文件中声明成extern变量,其他的源文件也可以使用这个变量

内存检测工具

  • 第一步:包含以下头文件

    #define _CRTDBG_MAP_ALLOC

    #include<stdlib.h>

    #include<crtdbg.h>

  • 接管new操作符

    #ifdef _DEBUG

    #ifdef DBG_NEW

    #define DBG_NE new(NORMAL_BLOCK_FILE,_LINE)

    #define new DBG_NEW

    #endif

    #endif

  • 在代码结束输出内存泄漏信息

    CrtDumpMemoryLeaks();

获取热键

  • #include<conio.h>

    bool quit=false;

    do{

    ​ if(_kbhit()){ //_kbhit()如果有敲击键盘,则返回true

    ​ }

    }while(quit==false)

|--------------|

| public 方法1 |

| public 方法2 |

|————-------|

| private方法1 |

| private 数据1 | //private方法或者数据都是为实现外部方法而设计的

| private 数据2 |

|----------------|

  • 定义一个类:

    calss Human{

    ​ public: //公有的,对外的

    ​ void eat(); //成员函数

    ​ string getName();

    ​ private: //私有的

    ​ string name;

    }

  • 把函数体写到 Human.cpp 文件中

    string Human::getName(){

    ​ return name;

    }

  • 对象的使用:

    int main(void){

    ​ Human human; //通过特殊的数据类型(Human类)来创建一个对象

    ​ 法1. human.eat();

    ​ 法2. Human *p;

    ​ p=&human;

    ​ p->eat();

    }

构造函数

1. 构造函数:对对象内部数据成员进行初始化

  • 特点:自动调用、函数名和类名相同、没有返回类型、可以有多个构造函数

    Human ::Human(string name,int age){

    ​ this->name=name; //实现(函数体)

    ​ this->age=age;

    }

2. 拷贝构造函数:

  • 定义:Human(const Human &other);

  • 实现:Human::Human(const Human &other){

    ​ name=other.name;

    ​ age=other.age;

    ​ }

  • 补充:const 加在函数的后面,表示不会去修改成员数据

    void getName(const string name)const ;

3. 赋值构造函数:

  • 定义:Human & operator =(const Human &other);

  • 实现:Human & Human::operator=(const Human & other){

    ​ if(this==&other){ //防止对象给自己赋值

    ​ return *this;

    ​ }

    ​ name=other.name;

    ​ age=other.age;

    ​ }

4. 析构函数: 对象销毁前,做清理工作

  • 定义: ~Human(); //自动调用

  • 实现: Human::~Human(){

    ​ delete addr; //addr 分配的内存空间

    ​ }

6. 补充: this指针: 特殊的指针,指向对象

类的静态成员函数(static)

  • 定义:static int getCount();

  • 初始化:static int humanCount;

    ​ int Human ::humanCount=0;

  • 通过类名直接调用(与具体的对象无关): Human::getCount();

  • 只能访问同一类型的对象,不可以访问普通类型的成员

初始化列表

  • const 类型

    const int age;

    通过初始化列表进行初始化 Human::Human():age(18){

    ​ name=“无名氏”;

    ​ }

建模手段

​ **1. ** 组合、聚合

​ - 组合:同生共死

2. 聚合: (用指针)

  • Cpu *cpu;

    //加一个接口,把指针传进去

    void add(Cpu *cpu);

Vector 顺序容器

**1. ** stringstream ret; //往里面塞各种东西,都转换成字符串

​ ret<<name<<“女–颜值”<<yanzhi<<“-年龄-”<<age;

​ return ret.str(); //转换成C++字符串再返回

**2. ** vectordata; //相当于 int data[];

3. vector<vector>data; //相当于 int data【】【】

4. 尾部添加 data.push_back(1); //相当于数组的的一个成员是1;

5.vector::iterator it =monster.begin();

​ it!=monster.end(); //it(迭代器)是一种特殊的指针,指向monster的第一个成员

6.求容器的大小(不在分配内容的前提下,容器最大可以包含数据的个数)

vector<int>v1(10);
v1.capacity();    //求容器的大小(10)
赋值:   v1.assign(2,88);    //修改容器中数据的个数和值

7.重新调整Vector 的大小

1. v1.resize(2);  //截取后面的数据,重新定义大小
2. v1.resize(13,888);  //重新定义大小,扩大时指定新增的值
8.尾部删除元素:   v1.pop_back();
9.访问第一个元素的值:   v1.front();
10.插入: 插入一个元素  v1.insert(vi.begin(),888);   //在第一个元素的位置插入888
         插入多个元素: v1.insert(v1.begin(),3,888);
//在第一个元素的位置插入三个888
11.删除   把整个vector都干掉  v1.clear();
		 干掉单个元素  v1.erase(v1.begin());
 //干掉第一个元素
 	干掉多个元素: v1.erase(v1.begin(),v1.begin()+3);

继承和派生

  • 公有继承:class Son :public Father{ //构造函数和析构函数不能继承,权限访问不变

    ​ public:

    ​ . string getName();

    ​ private:

    ​ string name;

    ​ }

    //先调父类构造函数,再调子类构造函数

  • Son ::Son(const char *name,int age , string game):Father(name,age){…}

  • protected 访问权限(希望被自己的子类访问吗,但是不能被外部访问)

  • 私有继承(private):父类中的函数被继承后,访问权限都变成private,

    class Son:private Father{…}

  • 保护继承(protected ):只把public 降为protected, 其他的不变

  • 子类的构造函数: 没有指定的构造函数,就会自动调用父类的构造函数

    ​ Son (const char * name,const char *game){

    ​ this->game=game;

    ​ this->name=name;

    ​ }

  • 子类型的作用: 形参作基类交换对象时,实参可以是派生的对象

    …demo:

    ​ void k(B b){…} ;

    ​ A a; //子类

    ​ B b; //父类

    ​ k(a);

  • 多重继承关系的构造函数: D(形参列表):A(实参列表),B(是参列表),C(是参列表){

    ​ //其他操作

    }

友元

  • 两种形式

    有元函数(friend void getName())、友元类(frind  class   Boy)
    friend  void updata(Human *human);
    
  • 友元类(声明): friend void Human::updata(Human *human);

  • 注意:1 个头文件中,不能再包含1个头文件 (Boy.h 中 不要包含 Gril.h)

运算符的重载

  1. +重载

    class Cow       class  Goat    class   Pork    //三个类
    Pork  opreator+(const Goat  goat);
    
  2. 输出运算符的重载

输出:ostream &  opreator<<(ostream  & os)const ;
  1. 类型运算符的重载,不需要返回类型

    operator  int ()const;
    

多态

  1. 虚函数表: virtual

    virtual void getName();
    
    • 单个的
    • VS的对象内存分析:项目命令行配置中添加:/dl reportSingleClassLayout Father(类名)
  2. 使用继承的虚函数:

    • 直接复制父类的虚函数表
    • 如果子类重写了父类的某个虚函数,那么就在这个虚函数表中进行相应的替换
    • 如果子类增加了新的虚函数,就把这个函数增加到虚函数表中(末尾添加)
  3. 多重继承的虚函数表:

  4. 进阶:final 用来修饰类,让类不能被继承

    • class XiaoMi final{

      ​ …

      }

  5. override 告诉程序员重写父类的虚函数(仅能用于修饰虚函数)

    class Father{
    	public :
    		virtual void func();
    }
    class Son:public Father{
    	void func()override{};
    }
    
  6. 习惯:最好在基类的虚构函数前加virtual

纯虚函数和抽象类

virtual void eat()=0;     //用法

核心模块(泛性编程)

  1. template<typename T>  //template  关键字告诉C++编译器,我要开始泛性编程了,
    //T-  参数化数据类型
    T  MAX(T a,T,b){
    	return a>b?a:b;
    }
    
  2. 模板函数和普通函数

    • 当模板函数和普通函数都匹配时,优先调用普通函数.
  3. 模板类: Son son //类模板必须显示类型

  4. 类模板和继承

    1. 当父类是模板类时,子类是一般类,父类必须在子类里初始化父类的类型
    class B:public A<int>{
    	......
    }
    
  5. 类模和友元函数

    类里面声明:
    template<typename T>
    frind void getName(Son<T> &son);
    

异常处理机制

int man(){
    if(fp==NULL){
    throw -1;
    }
}
int main(void){
	int ret=0;
	try{
	   ret=man();
	}catch(int error){
	printf("出现错误%d",error);
	}
    return 0;
}
  1. 异常处理接口声明:可以在函数声明中列出可能抛出的异常类型,加强程序的可读性.

    int max() throw(int ,string *,float){

    ​ //…

    }

  2. throw 类对象异常处理:

    • 使用引用类型捕捉,抛出匿名对象

      class Student{};
      抛出:   throw Student();
      
      捕捉:catch(Student &error){
          //-----
      }
      
    • 如果是动态分配的对象,直接抛其指针

      throw Student();
      捕捉:catch(Student *error){
      //-----
      }
      
  3. 注意:引用和普通形参传值不能共存.

  4. 继承和异常(多态vritual)

STL(标准模板库)

  • 算法
  • 容器
  • 迭代器

deque 容器

  • 带参构造

    //给定区间
    deque<int>d1(d2.begin(),d2.end());   //将区间[beg,end)中的元素拷贝给本身
    deque<int>d1(10,0);   //指定n个元素进行拷贝
    deque<int>d1(d2);    //拷贝构照
    
  • 在头部添加: d1.push_front(2);

  • 删除第一个元素: d1.pop_front();

  • 交换元素: d1.swap(d2);

list容器(双向链表)

  1. 拷贝构造函数 list(const list &lis);
  2. list的删除: list.remove(elem); //删除容器中所有与elem匹配的值
  3. 反序输出: listA.reverse();

C++11新特性(完美转发和变参模板)

//  大大提高效率
Sthudent stu;
vector<Student> A;
A.emplace_back(18,"吴献丰");  //增加效率,避免拷贝问题   相当于.push_back();
A.emplace(A.begin(),19,"罗佳荟");  //相当于.insert()

set和multiset 容器

  1. set 不允许插入相同的元素

  2. musltiset 可以插入相同的元素

  3. 仿函数(函数对象)function

  4. set的插入和pair的用法

    pair<set<int>::iterator,bool> ret=setInt.inser(5);树
    cout<<*(ret.first)<<endl;
    cout<<ret.second<<endl;
    

    5.查找

    set.find(k);  //查找k元素,返回指向k的迭代器
    set.count(k);  //返回容器中k的元素个数
    set.lower_bound(k);  //返回第一个>=k的元素的迭代器
    set.upper_bound(k);  //返回第一个>k的元素的迭代器
    set.equal_range(2);  //返回容器中与2相等的上下限的两个迭代器  1  2(起)  3(终)  4
    pair<set<int>::iterator,set<int>::iterator> it=set.equal_range(k);
    

Map和multimap 容器

  • 关联式容器,键值存储(key,value)

  • 区别: map支持唯一的键值,每个键只能出现一次

    ​ multimap中相同的键可以出现多次,不支持[]操作

  • map<int,string>mapStu;
    //插入
    mapStu.insert(pair<int,string>(1,"吴献丰"));
    //使用make_pair
    mapStu.insert(make_pair(2,"张山"));
    //使用value_type
    mapStu.insert(map<int,string>::value_type(3,"王二"));
    //使用[]
    mapStu[4]="李四";
    

queue 容器(队列容器)

priority_queue (优先级队列)

stack容器 (堆栈容器)

  1. 基于deque实现的

STL的疑难杂症

  • 任何时候在模板(template)中使用一个嵌套的从属类型名称时,需要再前面加关键字 typename

    template<typename T>
    void ptint(const list<T>& student) {
    	string line(50,'-');
    	typename list<Student>::const_iterator it = student.begin();
    	while (it != student.end()) {
    		cout << *it << endl;
    		it++;
    	}
    	cout << "student.size():" << student.size() << endl;
    	cout << line << endl;
    }
    

C++11

1- explicit(关键字),明确的,清楚地 explicit student(int age);

作用:表明构造函数是显示的,而非隐式转换

student x(18);  //显示构造
student x=18;    //隐式构造
student x={18,"王小美"};  //隐式构造

2- 左值和右值的概念

3- array (容器) 代替C语言中的数组

  • 特点: 大小固定,无法动态的扩展和收缩

    array<int,4>k;   //构造  int类型,大小4
    k.fiil(666);    //用特定的值填充array中的所有元素
    

4- 类型转换

int *addr=(int *)OX8888;//强制类型转化,整数直接变成指针

static_cast:   静态类型转化,  如将int 转成char
int i=staic_case<int>(PI);
  • reinterpret_cast :动态类型转换,重新解释,不同类型间的转换,数值与指针的互转

    用法:TYPE b=reinterpret_cast<TYPE>(a);
    TYPE 必须是指针\引用\算数类型\函数指针
    
  • dynamic_cast 动态类型转换

  • const_cast; 去const属性(仅针对指针和引用)

  • char p[]="123456";
    char *p1=const_cast<char *>(p);
    p[0]='A';
    注意:1 常量字符串不能去const属性
        2 在去常量限定时,要保证指针所指向的内存能够被修改,不能修改会引发异常 
    

5- 智能指针

  • 原理:将动态分配的内存交给一个有生命周期的对象,来解决指针自动释放的问题.
  1. auto_ptr //在C++11后被抛弃 不支持数组

    用法:#include<memory>
    	auto_ptr<类型>变量名(new 类型)
    demo:
    auto_ptr<string> str(new string("w"));
    auto_ptr<vector<int>>av(new vector<int>10));
    
    - Tset *temp=str.release();  //取消指针动态内存管理,之前的内存需要手动释放
    - delete temp;
    
    -str.reset(t1);  //改变智能指针的指向,将原来的置空,重新指向t1的地址,什么都不传,默认空指针,将原来的地址置空.
    
    

    2.unique_ptr - 支持对象数组管理

class D{    //删除器,重载()
public:
    void operator()(T *pt){
        delete pt;
    }     
}
unique_ptr<int[]> ui(new int[10]);   //会自动调用delete[]函数释放
unique_ptr<T[],D>p(new T[]);    //接收D类型的删除器,来释放

​ 3.陷阱: 赋值一定要使用移动语句: p1=move(p2);

  1. shared_ptr 一对多(共享指针)

    shared_ptr<T> sp;   //空的shared_ptr  可以指向类型为T的对象'
    shared_ptr<T>sp5(new T(),D());   //接受一个D类型的删除器,用D删除器来释放
    sp.use_count();   //显示接管T的指针的数目
    
    make_shared    //初始化对象(建议使用),分配内存效率高,返回指向对象的shared_ptr
    用法:  shared_ptr<string>p4=make_shared<string>("字符窜");
    
    重置:  up.reset();  //将up指针置为空指针,所管理的对象引用计数-1
    	  up.reset(p1);    //将up重置为p1的值,  p1是需要管理的指针
    demo:
    	shared_ptr<Person>sp10=make_shared<Person>();
    	Person *p10=new Person(10);
    	sp10.reset(p10);
    使用陷阱:
    		shared_ptr<Gril> sp_gril(new Gril());
    		shared_ptr 作为被接管的对象成员时,小心因循环引用造成的无法释放资源
            解决方法:  weak_ptr (弱指针)  ;// 配合shared_ptr    use_count不会+1
    		使用: weak_ptr<gril>wp_gril;   //定义一个空的弱指针
    			 weak_ptr<gril>wp_gril(sp_gril);   //定义一个共享构造
    	  
    
    1. 结构体内存对齐

      原因:1 平台原因
           2 效率原因   时间换空间
      总大小为最大数的整数倍
      #pragma pack(4);// 告诉编译器按照4个字节对齐结构体
      

    ### 补充

    判断是否有鼠标点击(左键),有的话返回这个消息
    ExMessage msg;
    peekmessage(&msg &&msg.message==WM_LbuuttDNOWN);
    

一个D类型的删除器,用D删除器来释放
sp.use_count(); //显示接管T的指针的数目

make_shared //初始化对象(建议使用),分配内存效率高,返回指向对象的shared_ptr
用法: shared_ptrp4=make_shared(“字符窜”);

重置: up.reset(); //将up指针置为空指针,所管理的对象引用计数-1
up.reset(p1); //将up重置为p1的值, p1是需要管理的指针
demo:
shared_ptrsp10=make_shared();
Person *p10=new Person(10);
sp10.reset(p10);
使用陷阱:
shared_ptr sp_gril(new Gril());
shared_ptr 作为被接管的对象成员时,小心因循环引用造成的无法释放资源
解决方法: weak_ptr (弱指针) ;// 配合shared_ptr use_count不会+1
使用: weak_ptrwp_gril; //定义一个空的弱指针
weak_ptrwp_gril(sp_gril); //定义一个共享构造


5. 结构体内存对齐

   ```C++
   原因:1 平台原因
        2 效率原因   时间换空间
   总大小为最大数的整数倍
   #pragma pack(4);// 告诉编译器按照4个字节对齐结构体
   ```

### ###  补充

```C++
判断是否有鼠标点击(左键),有的话返回这个消息
ExMessage msg;
peekmessage(&msg &&msg.message==WM_LbuuttDNOWN);
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零二年的冬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值