c++_sketch

目录

一、已经有C了为什么还要有C++

二、C++基本语法

三、函数

四、

五、模板

六、输入输出流

七、异常处理

八、标准模板库STL

九、附录

扫描二维码关注公众号,回复: 4837386 查看本文章

正文

一、已经有C了为什么还要有C++

C是面向过程的而C++是面向对象的语言,能够用封装、继承、多态的知识解决实际问题,有时候用C或C++都能解决同一问题,但是用 C++做C的补充可能会好些。

二、C++基本语法

1.    数据类型、常量和变量、语句,运算符和表达式

这部分兼容C,另外多出一种数据类型:类类型,最典型的就是向命令行输入输出的<iostream>了。

2.    new和delete

动态内存分配和销毁,C语言用的是malloc()和free(),主要是在动态数组的地方会用到;C++的则是使用new和delete,为指针pointer分配内存空间。一个好的习惯是new和delete成对出现。

(1)   用法

new 类型       分配一个该类型的对象

new 类型(初始值) 分配一个该类型的对象,并初始化

new 类型[数组大小]    指针将得到该数组的首地址,而且数组的类型、长度已经确定

三、函数

析构函数不能在类里面使用,构造函数在类的外面只能使用一次

1.    函数的基本概念

友元函数:友元函数不是类中的成员函数。

常函数:函数定义的最后有个const,比如int func()const,这种函数不能修改类中的成员变量(除非是mutable声明的变量)、只做简单的返回。

函数的参数:const后面的变量不能做左值;数组、指针做参数会用到*,其他情况尽量用引用&;如果不做左值,返回类型尽量是“const 类型&”。

有副作用:会改变当前类中成员变量,如果要返回用“*this”。

2.    缺省函数

C++函数的参数是可以有默认值的,而且默认值只能是从左往右依次缺。

3.    内联函数

4.    重载函数、运算符重载

(1)重载函数

函数名相同,但是参数表不同的一组函数,是不是重载函数和返回类型无关;参数表不同指的是参数类型或者参数个数不一样。

(2)运算符重载

有两种重载方式,成员函数重载、全局函数重载,它们的参数都有一定的对应顺序。成员函数重载最多能有一个参数、全局函数重载必须有两个参数并且要定义成友元,比如输入输出重载。

①可以重载的运算符

一元运算符

++  --

算术运算符

+  -  *  /  %

关系运算符

==  !=  <  <=  >  >=

逻辑运算符

!  &&  ||

位运算符

&  |  ^  ~  >>  <<

赋值运算符

=  +=  -=  *=  /=  %=  &=  ^=  |=  >>=  >>=

其他

[]  ()  ->  ->*  new  delete

②一元运算符重载的特殊情况

//一元运算符前缀形式

const 类型& operator++ ()

{

       某些成员++;

       return *this;

}

//一元运算符后缀形式,before调用的构造函数

const 类型 opetator++(int)

{

       类 before(某些成员变量);

       某些成员变量++;

       return before;

}

//自定义类型转换

operator 类型()

{

       return static_cast<类型>(某些成员变量);

}

③输入输出重载

必须使用友元、全局函数重载,因为重载的参数是有顺序的,输入输出重载的左操作数是流对象、不是当前对象。

friend istream& operator>>(istream&,type&);

friend ostream& operator<<(istream&,const type&);

之后在类外面定义函数,由流到对象(返回表达式)或是对象到流(返回流)

④重载赋值运算符

深拷贝:完全复制一模一样的数据内容,这样读写就是自由的、因为读写自己的数据不会影响到同类对象的读写;缺点是需要内存做开销。

浅拷贝:编译器的默认拷贝方式,简单的按成员对象依次拷贝;缺点是遇到指针、结构体等复杂对象可能会出错。

引用计数、写拷贝:这是一种结合深拷贝和浅拷贝的拷贝方式,用指针得到想要的资源并记录引用数、当引用数为0的时候销毁资源;当引用数大于1而且需要写的时候才做深拷贝。

OwnArray<T>& operator=(const OwnArray<T>& obj)

{

    if(this!=&obj)

    {

        //销毁原来的数据

        ExdOwnArray();

        //更新数据,运算符重载一个特别的地方是,可以访问对方的保护甚至私有对象

        arrLen=obj.arrLen;

        arr=(T*)malloc(arrLen*sizeof(T));

        int i;

        for(i=0; i<arrLen; ++i)

        {

            arr[i]=obj.arr[i];

        }

    }

    return *this;

}

5.    命名空间

为避免函数名冲突引入的一种机制。

定义一个命名空间namespace 空间的名称{…},使用的时候是空间名称::对象,或者提前声明using namespace 空间名称;。

四、类

类体现了封装、继承、多态的特点

1.构造函数、析构函数

2.访问限定

(1)访问限定字

public、protected、private,public在类中类外都可以被调用,protected和private在类中可以调用但是受保护、在类的继承中可以体现这一点。另外如果在代码中对象不声明访问限定字,那么它默认是private的。

(2)友元

(3)句柄

3.const和static限定字

4.类的继承和包含

继承和包含主要目的是代码的复用

(1)继承的用法

class 派生类名称: [访问限定字] 基类名称, [访问限定字] 基类名称,…, [访问限定字] 基类名称

{…初始化基类、其他类、成员对象…};

访问限定字默认是private;基类的初始化写在派生类的初始化列表中,否则基类将调用默认的构造函数;用于多重继承的基类之间如果有相同的函数名,调用的时候可能出现二义性的问题,可以通过显式指定类名的方法来解决;同一个基类如果多次间接继承,避免二义性问题还有一种解决办法,就是虚继承(在访问限定字的前面加上virtual);析构函数的执行顺序和构造函数的调用顺序是相反的。

(2)不同的访问限定字造成的继承差别

基类的private对象只能是基类自己和它的友元可以访问、也就是说private对象不能被继承,所以有了protected这种类型;继承得到的变量也是可以改变它的访问权限的,比如继承得到protect的对象、可以再把它声明成private,方法是“private: 基类::对象”。

访问限定字

基类中的public

基类中的protected

public

继承得到public

继承得到protected

protected

继承得到protected

继承得到protected

private

继承得到private

继承得到private

(3)不能被继承的对象

基类的构造函数、析构函数、赋值重载函数。

(4)包含

这是另一种代码复用的方法,做法是将其他类作为新类的数据对象,显然要实现相同的功能还是要写不必要的代码。所以相比继承,包含通用不易出错、继承常用但有时候难用。主要是多继承存在着复杂的初始化顺序,如果有些类还没有初始化就调用它,这是有问题的。一种解决的办法是用包含,另一种解决办法是所有的基类都有自己的默认构造函数,继承的时候重新初始化它们的数据即可。

五、模板

1.    用法

模板的定义

template <class T0,T1,...,Tn>

定义和参数相关的类、函数或结构体(其中T0,T1,...,Tn是自定义的参数类型)

模板的实例化

类或结构体<T0,T1,...,Tn>,函数不需要这样的实例化,因为填入参数的时候就知道对应的类型了

其中T0,T1,...,Tn是自定义的参数类型

六、输入输出流

需要头文件#include <fstream>;输入输出流最终都需要用close()关闭文件;对错误的输出cerr,ctrl+z中止程序运行、结束符EOF,ctrl+c结束程序运行。

1.istream对象

比如cin、读文件ifstream、字符串输入流istringstream

cin.get(ch);

接收任意字符,包括不可见字符,输入先写到ch,再到输出流

ch=cin.get();

EOF判断是否输入结束

cin.get(char*,int,char delim=’\n’);

从输入中读取一定长度的字符到字符数组中,读到delim停止读取

cin.getline(char*,int,char delim=’\n’);

从输入中读取一定长度的字符到字符数组中,读到delim停止读取

getline(istream&,string&,char delim=’\n’);

将读到的内容写到字符串,这种方式更实用些

cin.read(char*,int);

从输入中读取一定长度的字符到字符数组中

cin.gcount();

实际读取的字符数

2.ostream对象

比如cout、写文件ofstream、字符串输出流ostringstream

cout.put(ch);

打印任意字符,包括不可见字符

cout.write(char*,int);

写一定长度的字符串

ofstream obj(“文件名”,模式);

初始化一个ofstream对象并打开文件,模式可以是ios::in只读、ios::out只写、ios:app追加,模式视情况可以省略

ofstream obj;  obj.open(“文件名”,模式);

初始化一个ofstream对象并打开文件

3.字符串流

需要头文件#include <sstream>,字符串流可以起到一种桥的作用(类型转换,如果stringstream需要循环使用一定要先clear()),写到字符串流再从字符串流中读出;其中.str();将字符串流转换位字符串string,.str(const string&);在字符串流中写入新的字符串内容。

4. 操纵符

一般写在要操作对象的前面

showbaseboolalpha

布尔值文字输出

showbase

显示进制的前缀

showpoint

总是显示小数点

showpos

正数显示+

uppercase

十六进制0X、科学计数法显示E

*dec或者dec

十进制显示

hex

十六进制显示

oct

八进制显示

endl

换行

七、异常处理

八、标准模板库STL

1.顺序容器

容器

头文件

说明

vector

#include <vector>

动态数组

list

#include <list>

列表

deque

#include <deque>

双端队列

stack

#include <stack>

queue

#include <queue>

队列

priority_queue

#include <queue>

优先队列

九、附录

猜你喜欢

转载自www.cnblogs.com/guomc/p/10242323.html