数据类型

基本类型

int   double	float	char   bool
 
    类型 变量名 =
   
    
string   /*字符串,用此类型需包含同名头文件*/
    std::string 变量名 =
 
 
    
complex	 /*复数,用此类型需包含同名头文件*/
    complex< 类型 > purei( 实部, 虚部 )

把一个类型变量的值赋予另一个类型变量,值会自动转换类型以适应。

const 额外的声明,表示常量
	
	const 类型 变量名 = 值

容器类型

向量

必须包含头文件

#include <vector>
vector  
 
	vector<元素类型> 向量名(元素数)  
	\\仅声明时,元素数可以不声明

向量没有显式赋值方式。有几种初始化方法

vector<元素类型> 向量名(元素数,初始值) \\声明时加一个参数,全部初始化为该值
vector< 元素类型 > 向量名( 数组名, 数组名+6 ) \\截取数组的一段元素,数组名本身指向第0个元素
vector< 元素类型 > 向量名(向量名)  \\用另一个向量赋值
数组

内置数组不能批量操作

	元素类型 数组名[元素数] = {} //声明和赋值数组
	数组名[索引]		//引用元素
	元素类型 数组名[元素数][元素数] = {{}} //多维数组,一般用循环赋值

数组名大多时候本身指向第一个元素的地址

数组名 == &数组名[0]
map

类似于字典,由键值对组成。

#include <map>
 
map<键类型, 值类型> map名; //声明map
 
map名[ 键类型(键) ] = 值; //插入键值对
集合

功能类型

地址(指针)

我们管指向地址的变量称为指针

&  	/*取地址操作符*/
*   /*解引用操作符,将指针反向索引至原变量*/
	
    &变量名 /*返回变量地址*/
  
	类型 *指针名= &变量名 /*定义指针时的类型是原变量类型,获取地址*/
    
    *指针名 = /*操作解引用指针,等于直接操作原变量*/
    
    类型 *指针数组 [] = { &ix, &jx, &kx }; //用数组批量获取指针

不能给 定义好的指向某类型变量的指针 赋予其它类型变量地址。

void *指针名 = &任意类型变量  // void 类型指针可被赋予任意类型变量的地址。除了函数。

指针命名习惯是p+原变量名

引用

一个变量的别名,目前看来比较多此一举。

int &别名 = 变量名 //声明引用的同时必须用变量赋值,否则报错

学到的作用:

  • 指定函数的形参为引用,只会传入指向原数据的别名;而指定形参为对象本身,会拷贝一份对象的副本传入。

    如果对象占内存很大,传入引用可以节省拷贝的计算开销和内存占用。

  • 传入引用可以修改原对象,传入一般对象只会拷贝副本操作。

    • 对象需要修改时,传入引用

    • 对象内存大,无需修改时,需要省内存,防修改。传入 const 引用

    • 对象内存小,无需修改时,传入const 对象,也可传入const 引用

枚举

用于限制传递的参数在一个集合内,否则报错

enum 枚举名{ 变量1 = 值, 变量2, 变量3 }
 
枚举名 om 	//形式地指代枚举成员

被定义的枚举名可作为类型标识符

整体结构

创建类对象 在c++中,类等同于用户自定义的数据类型。

一个类对象,声明即定义了全部的状态——其“值”

类名 对象名(参数表) 

结构框架

class classname {
private:// 私有部分,一般是类的成员变量,不能在外部被调用
	
    //声明成员变量 1
    //构造函数
    //析构函数
    //成员函数
    
    
public:// 公有部分,一般是函数,能在外部调用
	    
    //声明成员变量
    //构造函数 1
    //析构函数 1
    //成员函数 1
 
};
  • 成员变量——可认为是类的”属性”。公有的成员变量能用 . 访问类对象。私有的用在共有部分定义的getter函数获取,setter函数修改。

  • 构造函数——初始化成员变量,需要参数或用默认值。与类同名,可以任意多个,创建类对象时会自动根据参数模式匹配对应的构造函数

  • 析构函数——在类对象局部作用域结束时自动调用,释放其内存。不是必须的,一般要用的情况是,类中有用new分配的动态内存对象,要在析构函数中用delete删除它。

  • 成员函数——实现类对象功能的部分。无非是读取和操作成员变量,或者也可和成员变量无关。

成员变量

可认为是类的”属性”。公有的成员变量能用 . 访问类对象。私有的用在共有部分定义的getter函数获取,setter函数修改。

一般声明:

类型 变量名 //一个成员变量声明即自动占用内存,是无意义的随机值。可在后续函数中赋值	

一般成员变量不是必须有初始值。但对于要实现特定功能的类,往往有些成员变量必须要有一个初始值。 这些初始值可以直接声明时指定:

类型 变量名 = 值;

也可以用构造函数成员表/参数+操作 来指定。

特例:

const 类型 变量名 
 
类型& 别名 

const成员引用类型 必须指定初始值。且只能用成员表指定。

构造函数

构造函数必须与类同名,被调用在一个类对象被声明之时。 负责给那些必须要有初始值的成员变量设值初始值。(功能要求有初值的变量/const/引用)

//结构 
类名(参数表) : 成员表 {操作} 
//具体语法
类名(类型 变量名,类型 变量名):成员(初始值),成员(初始值){操作}

参数表——将会用于匹配创建类时传入的参数,并用这些参数搭配函数操作,为类成员赋值。

成员表——直接指定成员的初始值。

例子:

//默认构造函数————指定无参数时的默认值(即全用成员表赋值)
类名():成员(初始值),成员(初始值){}
 
//带参构造函数————带操作,用变量给成员赋值
类名(类型 变量名){赋值操作}

构造函数可以有任意多个,但参数表必须不同。生成类对象时会调用其参数表与传入参数匹配的构造函数。

析构函数

在类对象局部作用域结束时自动调用,释放其内存。 类对象的成员变量,大多类型都会在类结束生命周期时自动被释放内存,不需要用析构函数。 一般要用的情况是,类中有用new分配的动态内存对象,要在析构函数中用delete删除它。

~Student() {
    delete 动态变量
}

成员函数

//getter函数,一种规范的函数,在外部调用此函数来获取private中变量的值

//setter函数,一种规范的函数,在外部调用此函数来修改private中变量的值
         ...
//承诺const的函数,定义时在函数名右边加const关键字,创建为const的类对象只能调用其内部同样声明了const的函数或共有成员。作为一种规范,凡是不修改成员变量的函数通通声明const 。

//重载函数,operator+运算符构成的函数,承诺const,参数传入类的const引用。
用于重定义运算符作用于类上的行为。

// 一般功能函数
返回类型 函数名(参数表) const {}
返回类型 函数名(参数表){} 
 
class Student {
    
private:  
     
    类型 变量名; //一个成员变量声明即自动占用内存,是无意义的随机值。可在后续函数中赋值。
	
    const 类型 变量名; //如果声明const成员,则所有构造函数必须用成员表设置初始值。
    类型& 别名 //引用类型的成员一样,必须设置初始值。
     
public: 
    /* 构造函数 格式为 函数名(参数表):成员表{ 操作 } */
    
    
    // 默认构造函数————初始化必要的成员初始值。创建类对象不传入参数时,调用默认构造函数。
    与类同名() : 成员(初始值),成员(初始值),成员(初始值) {一般无操作}
    // 带参构造函数————用传入的参数初始化赋值成员变量
    与类同名(类型 变量名,类型 变量名,类型 变量名):成员(初始值),成员(初始值),成员(初始值)
    {操作———根据参数赋值必要的成员变量}
 
    // 析构函数
    ~Student() {
        delete 动态变量
    }
 
    // 成员函数 (方法)
    
    
    	// Getter和Setter 访问和修改私有成员,命名习俗是get/set+原名(首字母大写)。
    std::string getName() const {
        return m_name;
    }
    void setName(const std::string& name) {
        m_name = name;
    }
 
    int getId() const {
        return m_id;
    }
    	// 一般功能函数
	返回类型 函数名(参数表) const {}
    返回类型 函数名(参数表){}
		...
    // 静态成员函数 (属于类本身,而非对象)
    static void schoolMotto() {
        std::cout << "求知若渴,虚心若愚。" << std::endl;
    }
 
// 再次使用访问说明符划分区域
protected: // 受保护成员,类内部、友元和派生类可访问
    // 这里可以放置一些计划让派生类继承和访问的成员
    // 例如: std::string m_protectedData;
};
 

基本知识

常用头文件

#include <iostream>  //用到cout / cin
#include <string>    //用到string
#include<vector>     //用到vector
#include<algorithm>  //用到sort
#include <windows.h> 

//现代编辑器使用utf-8保存代码但powershell/CMD默认使用GBk,这导致终端输出的中文被错误解码,显示乱码,解决方法是用此库的函数将控制台输出改为utf-8编码格式。
SetConsoleOutputCP(65001)

动态内存分配

在C++中,

对象可以静态分配——即编译器在处理程序源代码时分配

也可以动态分配——即程序执行时调用运行时刻库函数来分配

这两种内存分配方法的主要区别是效率与灵活性之间的平衡准则不同。静态与动态内存分配的两个主要区别是

  • 静态对象是有名字的变量我们直接对其进行操作而动态对象是没有名字的变量
  • 静态对象的分配与释放由编译器自动处理,动态对象的分配与释放必须用代码显式地管理。 它通过new 和delete 两个表达式来完成
没有名字的变量只有地址,用一个解引用的地址来操作,其赋值用new表达式
	类型 *指针名 = new 类型(值)  	/*赋值单个值的无名对象*/
	类型 *指针名 = new 类型[元素数]  /*初始化一个指定大小的数组,但无法赋值*/
用完的无名变量,用delete表达式删除,释放该地址的内存
	delete 指针名	/*删除单变量*/
	delete [] 指针名 /*删除数组*/

关键字&操作符

const

用于声明常量

const 类型 常量名 =  	//声明常量,在最前面加关键字const
 
const 类型 *指针名 = &常量名 //声明常量的指针,也是如此
    
返回类型  函数名(参数表) const{} //多用于类中成员函数,声明函数不改变任何成员变量。

对常量修改将报错

::

作用域解析符,表示从某空间解析出的某对象

  //类中解析出函数
	  //map中解析出键值对
null & nullptr

空变量 空指针

c++的便捷操作符,解引用后访问成员

operator

定义一般运算符在自己写的类上的行为。 比如两个类对象无法相+,因为没有定义它们的加法。

operator可以在类内部,自定义一个运算符作用于类上的效果。

方式是用operator和运算符构成一个重载函数。其它语法与函数相同。

返回类型 operator运算符(const 类名& other) const{}
//参数类型必须是 类对象的 const引用
//形参一般命名为other,意思是与此对象进行计算的另一个对象
//必须承诺const不修改对象状态
//假设的成员变量
int x;
 
//定义< , 类的比较方式
bool operator<(const 类名& a) const {
	return x<a.x
}

优先级

1.成员访问运算符 . 的优先级高于解引用运算符 *

案例:解引用指针操作类类对象,调用其函数

*findStudent(deactivate_id).deactivate() //此代码会优先解释为调用,对调用的结果使用解引用。不对。
(*findStudent(deactivate_id)).deactivate() //一种解决方法是用()改变优先级
findStudent(deactivate_id) -> deactivate() //另一种方案是->,它的作用就是先解引用再访问
 

基操

基本格式

一般语句;结束 {}后不需要;结束

语法不看缩进,表示嵌套关系用{ }。考虑可读性一般还是缩进。

单个语句可以直接换行。

输出控制
std::cout << "字符串" << std::endl   

语法解释:

std::cout	std命名空间的cout,输出流对象。指定标准输出到控制台。

<<			插入运算符,将右侧数据"插入"到输出流,可连接多个输出

std::endl	std命名空间的endl,行结束符,换行并刷新缓存区    (与使用'\n'换行的区别是每行生成即输出)
		
条件操作

一般的条件操作

if (布尔表达式)
{	
    操作;//操作只有一行时,不需要{}
}

条件表达式

条件式 ? True值 :False值 //根据条件返回对应值
循环
//传统循环
for ( 指标; 指标判断; 指标迭代 ){
    操作;
}
//容器循环
for(元素类型 元素昵称 : 容器名){ //如需修改容器元素,类型应是对应引用。否则指向的是元素复本。其它方法默认都能修改元素。
    操作;(元素昵称就是迭代器,指向元素本身)
}
//用迭代器的传统容器循环
for(auto it=容器名.begin();it!=容器名.end();++it)
while (bool值或表达式){
	操作;
}
break; //跳出循环
continue; //跳过单次循环的剩余语句
goto label;
...
label:   //跳转到标签锚点
迭代器

迭代器可理解为容器内部的指针,多用于循环操作。

所有容器类型都有begin()和end()成员函数

.begin()	//返回迭代器,指向第一个元素
.end()		//返回迭代器,指向最后一个元素
iter = a.begin(); //
++iter;		//前移迭代器,指向下一个元素
*iter = value	//指向原元素的值

项目规范

目录结构

规范性的构造。项目目录下应包含类的头文件,定义文件,主程序文件。

class1.h
class1.cpp
class2.h
class2.cpp
...
main.cpp
  • class.h 是头文件,用于储存类声明。
  • class.cpp 是类定义文件,将类内部函数定义在此文件中。
  • main.cpp是运行程序的文件。

头文件引用

要在运行程序中使用某个类,要通过引用该类的头文件。定义文件也需要引用该类的头文件。 方式是

#include "classname.h"

一个头文件不能被一个定义文件直接或间接多次引用,因此要在头文件中采取措施防止多次引用。 传统方式

#ifndef CLASSNAME_H
#define CLASSNAME_H

//代码内容

#endif

其含义是:

  • ifndef——如果没有导入过此头文件;
  • define——则导入此头文件;
  • endif——结束判断 这样写是在导入的同时,防止重复导入。

现代方式

#pragma CLASSNAME_H

效果同上,更加简洁。

编译并运行

进入项目所在目录用g++编译

g++ classname.cpp main.cpp -o 程序名

参数:所有cpp文件
选项:
	-o    执行文件名

编译后会生成.exe可执行文件,直接运行即可

.\程序名.exe