您的位置:首页 > 编程语言 > C语言/C++

C++学习心得(自己随意笔记,错误多多)

2016-10-11 11:15 375 查看
面向过程:自顶向下,程序出现bug,调试起来非常困难,层叠变化

面向对象:模块是类,而不是过程(函数),类是对象的集合,类中的对象具有共同的属性

数据和操作数据的过程都被封装或者说包含在类中,类中还有操作数据成员的函数成员,通常将这些函数成员称为方法

如果某个数据类型公开的公用接口为高级操作,而隐藏了所有的实现细节,称这个数据结构为抽象数据结构

模块指组装成程序之前能单独编写和测试的程序部分

在面向对象中,基本的程序模块是一个类

一个类是对象的集合,类中所有的对象共享类的属性和操作

定义类最后大括号要加分号;

class类中默认为private,只有类中方法和友元函数可以访问

公有成员是类的接口

在类里面申明函数时直接写出了函数定义,为内部定义方式,在类外面给出定义叫外部定义,需要加::类型
类名::函数名(){   };

可以通过在方法原型前加inline试外置方法变为内置

任何情况下设计的类都应该设计一个驱动对其进行测试

构造器:与类同名,但无返回值,可以有多个构造器,通过参数不同区分,构造器在用类定义对象时就会执行一次构造器里面内容

复制构造器:类名 新变量名(需要复制的变量名);得到一个和原变量的副本

explicit可以防止使用构造器时进行隐式的类型转换

每个数据成员都分配了空间,多个对象共用一个函数(方法空间),在代码段存放

析构函数无返回值,无参数,由系统自动调用(同构造函数一样),形式:  ~类名(无参数){。。。。。。};

在类中申明一个static数据,被所有对象所共用,必须在类外进行声明,如果想对其初始化,只能在类外面进行定义。

类中静态方法只能访问静态数据和静态方法。

一旦对类中数据或方法加以static(静态)并且其共有,则不仅可以通过类元素访问还能直接 类名::方法(数据)访问

int &b=a     //引用:相当于b为a的别名,b做任何操作都会影响a。

创建类时,class所有成员默认私有,struct所有成员默认公有。

类中const的数据成员只能在方法首部对其进行初始化。

编译器一般会自己提供复制构造器和重载类的赋值运算,使用有一定的危险性,通过改变复制的值会改变原有值。

 

存储:

内存系统3大区:

1.程序区:保存函数体代码及外部变量,静态变量,全局变量

2.栈:保存参数和静态非局部变量(我的理解是硬盘,容量大,速度较慢,cpu寄存器速度快,容量小),自动生成和释放

3.堆:动态创建(运行时创建),new,new[],delete,delete[]
 例:   double* p=new double[298];  delete[]p;用完记得释放,new一个类新对象时还会调用构造函数,也可以指定某个构造函数。

auto:代码块内默认为auto,定义在语句块中,生命周期在一个代码块

extern:外部变量默认为extern,需要定义声明,只能定义一次,定义可以省略extern,声明必须加extern,定义以上的代码块无法访问该变量,定义以上的要想访问该变量,需加extern声明,而定义以下的可自由访问。如果定义时加了extern,需赋初值以区分是定义还是声明,声明无法赋值。其他文件声明了该变量,也能访问该变量。

static:默认初始化值为0,静态,生命周期(非作用周期)都是整个程序的生命期,类内部定义static,共有成员;

      定义在块外,为全局变量,整个程序可调用(其他文件不可调用),定义在块内,其他块不能调用,但它生命周期并未结束。

可以定义一个外部变量为static,这个变量只对这个文件有效,以免和其他文件变量重复(相比于默认extern的好处)

可以将所有extern外部变量声明写在一个头文件里,只需#include” ” 即可。

   存储类别

最大作用范围

生命期

存储区域

   auto(内部默认)

代码块

代码块

堆栈

   static

单个文件

程序

程序区

   extern(外部默认)

整个大程序,多个文件

程序

程序区

 

 

 

继承:

基类中的私有成员不能被子类直接访问

子类添加的成员或方法与基类重名,基类的则被隐藏起来,要使用需加范围解析运算符 d.B::h   h为重名成员,B为基类,d为子类对象

protected(受保护成员),如果没有继承,受保护成员和私有成员一样,公有继承中,基类受保护成员在子类也是受保护的。

private和protected在继承时的区别:private不继承,在子类的方法中,不能使用,但可以通过基类的方法访问,protected可以继承,在子类的方法中也可以访问。

若D中成员d为private或protected,a是D的对象,a.d是错误的,不能直接访问。

基类不能访问子类中受保护的成员。

子类设置构造函数调用时必须调用基类构造函数(默认调用基类的默认构造函数),要么基类有默认构造函数,要么在子类构造函数申明调用哪一个基类的构造函数。具体如下图

 

继承中,构造函数顺序为从基类到子类,而析构函数的顺序为从子类到基类

一个子类可以继承多个基类  class D:public B1,public B2{......};

protected继承方式:基类protected和public在子类中皆为protected(在一个类里,protected和private没区别),基类private在子类不继承。

private继承方式:基类protected和public在子类中皆为private,基类private在子类不继承。

继承中,默认的继承方式是私有  class D:B{。。。}   私有继承

可以通过访问申明将继承成员申请为与基类相同的状态,如基类B中A为public,私有继承后A为private,可添加申明public:B::A;这样A就为公有。

 

多态:运行时绑定(多态),不是多态(编译时绑定)

只有方法才能用virtual

在基类中申明了虚函数就不用在定义或子类中使用virtual

多态3点要求:1.继承层次、2.不同层次有同名的虚函数、3.必须有一个指向基类的指针或引用,使用资格指针或引用调用虚函数。

new运算符可以动态(在程序运行过程中)创建一个类的对象,创建成功则返回新对象的地址。

构造函数不能使用virtual,析构函数可以使用virtual;

只有非静态方法可以使用virtual,类方法不能使用virtual,即static和virtual不能同时使用。

如果没有使用virtual,编译时就绑定了,例如*p定义时是指向基类的,运行时让其指向子类,由于不是虚函数,p指向的方法还是基类的。

名字重载:名字相同,参数不同

名字重写:虚函数,重写继承的虚方法

名字隐藏:不同基、子类中出现同名方法,且不是虚函数

将一个虚方法初始化为0时,只是标明这个方法是纯虚方法,包含这个方法的基类称为抽象类,抽象类不能定义一个对象,可以有子类,子类必须重写基类所有纯虚方法。

 

 

重载运算符:

operator+  可以看成是一个函数名

除  .  .*  ::   ?:  sizeof外都可以重载,每个重载的运算符,除赋值运算符=外都能重载。

类中语法:   返回类型   类名::operator<操作符>(参数列表){函数体};

例如:     complex  complex::operator    +   (const double参数不变){
记得返回一个对象 }(const表示调用的不会改变)

表示一个complex类和一个double类型进行+(不是相加)操作,返回complex类型,具体操作参照函数体

左边是调用方法的对象,右边是参数列表里的类型,双目运算符有一个参数,单目无(a++有一个int类型)。

通过重载后,优先级不会改变

顶级函数:c operator+(c& c1,c&c2)    c1,c2都为类c中方法

          a=operator+(b,c)                 //必须带有一个类的对象

[]  =  ()   -> 这4个只能用方法重载  ++a前置运算符可以进行重载,operator++(),a++后置,operator(int),参数int区分前后置,可以用,也可以不用。

顶级函数相对于类方法重载运算符优点在于,某些场合下可以交换两个数据位置,但用函数重载不能访问类的私有成员,可以将opretor+变成友元函数

友元函数:类似于private,public,protected的声明,friend
int fun(void);申明外部的fun为友元函数,可以访问类中私有成员

友元类:类F中每个方法都是类C的友元函数,不需要单个声明类F中的每个方法,可以将F声明为C的友元类。friend
 F;

 

 

 

模板:

template<class T1,class T2...>

函数模板:抽象一个函数

类模板:抽象一个类,使用方法:类模板名<数据类型>对象名

vector(动态数组)容器,包含在#include<vector>  v1.insert(v1.end()-1,3);倒数第二位插入3

erase为删除操作,若有一个vector迭代器it,v1.erase(it),会出现问题,可以写成it=v1.erase(it).

迭代器(iterator) 调用
vector<int>::iterator it;定义vector迭代器it   一般用*it取其值。

指针能指向函数,迭代器只能指向容器。

 

 

数值计算:

原码=补码变反码+1

 

逻辑与的优先级高于逻辑或

1||0&&0的值为1!!!

 

+=,-=,*=,%=这样的复合赋值运算的优先级与=的优先级一样

 

两个不同类型进行运算时,会将表示范围小的类型(提升!!)为表示范围大的类型,如char+int,会将char(提升)成int,但不会改变原有类型。

 

static_cast<需要转换成的数据类型>(需要转换的数据变量)

const_cast  转换常量

dynamic_cast 转换继承中的指针或参数

reinterpret_cast 独立实现的类型转换

 

atoi函数可以将字符串类型的数字转换为长整型

 

 

 

 

 

 

 

输入输出:

cin输入一个字符串时,略过前面的空白字符,读取一直到空格字符为止

endl----------------------------------换行

fixed---------------------------------用定点数的形式输出浮点数:d.ddd

left----------------------------------左对齐

right---------------------------------右对齐

scientific----------------------------用科学计数法的形式输出浮点数:d.dddEdd

setfill(c)----------------------------用C做填充字符

setprecision(n)-----------------------将浮点数精度设置为n

setw(n)------------------------------设置域宽为n--------------------------------------只有紧接着的一次有效

showpoint-----------------------------显示十进制小数的小数点和尾部的0

noshowpoint---------------------------不显示尾部的0,如果可以不显示小数点就不显示

showpos-------------------------------在非负数前显示“+”

noshowpos-----------------------------在非负数前不显示“+”

skipws--------------------------------跳过输入数据前的空白符号

noskipws------------------------------不跳过输入数据前的空白符号

 

 

 

 

 

头文件:

#include<fstream>  //关于文件的头文件

#include<iomanip>使用带参数的输入输出格式

#include<vector>向量:随机存储任何元素都能在常数时间完成,在尾端增删元素具有最佳性能

#include<deque>双端队列:随机存储任何元素都能在常数时间完成(性能次于vector),在两端增删元素具有最佳性能

#include<list>双向链表:任意位置传入删除元素效率高,不支持随机存取(比如像数组一样+3,偏移3),每个元素占用额外空间。(支持remove删除),在容器中间插入删除应采用deque。

 

 

 

算法algorithm\numeric(不一定适用于所有容器)

都为左开右闭

查找:find (first,last,val),左闭右开,first,last为迭代器,val为查找的值,返回val位置的迭代器,或end

排序:void sort(first,last)

取代:replace(firest,last,old,new)

反转排序:reverse(start,end)

统计:count(start,end,searchValue)

 

 

 

 

函数:

引用函数:值传递时,被调函数直接对实参进行计算,而不是对形参进行计算(类似于指针),在函数原型中加&可实现这一步骤。int fun(int &a,int&b);

数组的传递也是引用,直接对数组就行修改,而不是传递一个镜像。加const就不会修改其值。

文件函数输入ifstream输出ofstream都应采用引用传递&

 

一般的返回是把return值复制到临时存储区域,主调函数访问临时区域来访问其值,而int& fun(){....return i;}是直接访问i的值,少了复制这个步骤,但如果return的是一个fun中的变量,是无法访问的,因为fun结束后,fun中变量被释放了,所以该方法只能用于某种场合。

 

重载:多个函数用一个函数名根据参数的个数,类型的不同加以区分来调用不同的函数实现不同的功能。(不能用返回类型来区分函数)。

顶级函数可以使外部(extern)的,也可以是静态的,默认外部,外部作用范围为整个程序(多个文件,貌似不用声明),静态为单个文件。

任何类型指针不需要转换就可以赋给void*类型指针。

 

 

 

 

数组,指针,字符串:

一个指针p指向某个数组a[10]时,p
=a
;

‘\0’的值为0;

处理字符串的函数(包含在cstring里面)

strlen-------------------------------------字符串长度

strcat\strncat---------------------------把后面的字符串接到前面(去掉第一个字符串’\0’,第二个字符串第一个元素接到第一个原’\0’位置)

strcmp\strncmp------------------------比较两个字符串

strcpy\strncpy--------------------------复制字符串,注意用strncpys时,如果没复制到’\0’,需手动加上’\0’

strstr-------------------------------------搜索字符串中指定的字符串,返回搜索到出现的地址(最左边地址)

strchr------------------------------------搜索某个字符在字符串中出现的最左边的位置

strrchr------------------------------------搜索某个字符在字符串中出现的最右边的位置

strpbrk------------------------------------搜索后字符串中任意字符在前字符串中最左边的位置

strspn-------------------------------------得到从第一个字符串中,从左边开始搜索在第二个字符串中的字符的个数,strspn(“hello”,“heo”)输出2;

strcspn-------------------------------------得到从第一个字符串中,从左边开始搜索未出现在第二个字符串中的字符的个数,strspn(“hello”,“heo”)输出0;

Strtok---------------------------------------搜索第一个字符串当遇到第二个字符串中的字符时,将其替换成’\0’,在执行第二个语句时strtok(NULL,s)用null表示第一次执行时的第一个字符串,表示接着上次的字符串进行搜索。

将多维数组作为函数参数时,在函数原型里要指明除了一维之外其他维数的值

 

头文件cstring中还包含以mem开始的函数原型,如mencpy,memcmp,不仅可以以字符串作为参数,还可以用其他类型数组为参数,但一般要多加一个参数,表示需要操作的位数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐