C++基础
C++的难学,不仅在其广博的语法,以及语法背后的语意,以及语意背后的深层思维,以及深层思维背后的对象模型。希望唯一的坚持能使自己变得强大!
戎·码一生
自信来自实力,改变来自挑战。做一只生活小强。
展开
-
const、#define、typedef和inline的区别
一些小知识,怕忘记所以就记下来!方便以后复习之用,也希望可以帮到同行!首先来说一下const的作用吧!在c中:1:用来修饰变量,表示该变量是只读变量,不是常量。如const int pi=3.14;表示pi是一个只读变量,表面是不能改变!!为什么是表面上呢,,因为C语言中有指针:可以通过指针来改变:int *p= π*p=123; //这是可以的;还原创 2016-04-06 21:12:19 · 1731 阅读 · 2 评论 -
面向对象与面向过程的区别
学习C++一般都会思考这个问题,c++里的++到底比C语言多了什么东西,有什么不一样呢??首先一个问题就是类与对象,那么我们就必须要理解面向对象和面向过程的区别,经过查阅资料以及网上很多大神们的讲解,我小小总结一下,我喜欢用实例来讲解,所以比较的时候多以实例为主:1.面向对象和面向过程的区别:个人理解:一个博大,一个精深:博大:面向对象的博大,将某一类事物的共同属性进行抽象,将其所原创 2016-04-10 10:54:04 · 9013 阅读 · 3 评论 -
C++中的关键字--typeid
C++中有很多关键字,作为程序猿一族,用的少可以原谅,但是不知道就有点儿说不过去了,所以来说说typeid关键字的作用:主要作用是:返回指针或者引用所指对象的实际类型。用法:father *p=new father;cout下面来看一个实例:#include using namespace std;class father{public: int a ;原创 2016-04-10 16:49:52 · 1013 阅读 · 0 评论 -
explicit关键字的作用
explicit作用:在C++中,explicit关键字用来修饰类的构造函数,被修饰的构造函数的类,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换。explicit使用注意事项:explicit 关键字只能用于类内部的构造函数声明上。explicit 关键字作用于单个参数的构造函数。 在C++中,explicit关键字用来修饰类的构造函数,被修饰的构造函数的类,不能发原创 2016-04-10 18:34:39 · 2007 阅读 · 0 评论 -
C++中assert的作用
assert()这个函数在C++中用的比较少,但是有以次面试被问及到了,我就说了个中断,然后面试官让我过了,所以记录一下,查了下资料,原来如此!assert宏的原型定义在中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:#include void assert( int expression );assert的作用是现计算表达式 expression ,如果其值为假(即为原创 2016-04-10 20:53:44 · 16422 阅读 · 1 评论 -
C++如何实现单例模式
C++有时会用到单例模式,比如和数据库连接的类,我们只需要一个对象,那么这时候我们就要限制类对象产生的数量,允许一个类产生一个对象,如何让一个类产生一个对象呢,也就是实现单例模式?方法一:将构造函数声明为私有的,这样派生类,外部的程序就不能随意产生对象代码如下:#include using namespace std;class Single{public: static S原创 2016-04-10 22:02:10 · 881 阅读 · 0 评论 -
this指针
说到C++中的类,其中一个非常方便的地方就是,当我们将某一类具有相同属性和行为的封装成一个类后, 我们只需要用该类型创建不同的对象,那么就可以生成很多对象实例,类是对对象的抽象,它是一种抽象的数据类型,是一个抽象的概念,对象是对客观事物的抽象。对象是类的实例,类是对象的模板,万物皆为对象,对象属于某个类,对象的唯一来源于世界中事物的唯一;对象的唯一在程序中是地址内存的唯一;那么我们原创 2016-04-11 10:19:10 · 716 阅读 · 0 评论 -
指针对象数组的析构问题
类中在对象执行完它的行为后,生命周期结束,一般会调用析构函数来回收该对象所拥有的资源,那么如果该对象是一个数组,我们应该注意一些什么呢:先看下面一段代码:#includeusing namespace std;class father{public: int b; father() { cout<<"constructor"<<endl;; } ~father()原创 2016-04-11 10:40:56 · 4343 阅读 · 0 评论 -
C++对象的分割
C++中多态是一个很重要的泛型技术,通过函数的覆盖和重写,实现接口来提高代码的复用率,提高编程效率!!那么,在是实现多态的过程中,要注意什么问题呢?这里需要注意:多态的实现是靠指针和引用,传值就会导致对象的分割,不能实现多态 !!1.当一个派生类对象赋值给基类的对象时,会产生对象分割;2.基类对象强制转化派生类对象也会,也是强制转换后赋值;下面来看一个代码示例:#inclu原创 2016-04-11 11:40:09 · 1006 阅读 · 0 评论 -
纯虚函数
实现多态,用到了虚函数,还有一种是纯虚函数,这个类似java里面的接口,实现一个接口,也就是实现一个纯虚函数!纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它申明为纯虚函数,它的实现留给派生类去实现,这就是纯虚函数的作用!同时含有纯虚函数的类 称为抽象类,它不能生成对象!下面进入代码示例:#include using namespace st原创 2016-04-11 12:18:54 · 2728 阅读 · 0 评论 -
inline函数
对于内联函数,主要用在代码块比较小,并且频繁调用的时候,可以将函数定义为内联函数,这样可以在编译期间就将函数静态绑定,在函数调用处将代码展开,提高程序执行的效率。但此处又有几个问题,例如C++中,类的成员函数默认的都是内联函数,但是为什么又能是虚函数呢???不是说内联函数不能为虚函数吗??这不是矛盾吗??还记得在使用函数指针的时候,如果是普通的函数,函数的函数名和&函数名都是一样的原创 2016-04-11 18:52:03 · 709 阅读 · 0 评论 -
delete析构的调用
如果基类的析构函数不是虚函数,那么在new出来对象,最后delete回收的时候调用析构函数的原则:析构函数看指针是什么类型的,就调用那个类的析构函数,然后按继承的顺序,依次来调用父类的析构;主要看delete 后面跟的指针是什么类型的!!!!#include using namespace std;class A{public: int num; A() { num=原创 2016-04-11 21:24:23 · 2454 阅读 · 0 评论 -
虚继承
虚继承主要解决多继承中出现变量访问不明确的问题;解决方法:1.用类名+::来解决;2.虚继承;#include using namespace std;class A{public: int num; A() { num=100; cout<<"A"<<endl; } ~A() { cout<<"~A"<<endl; }};class B原创 2016-04-11 21:33:41 · 893 阅读 · 0 评论 -
虚表的地址与虚继承类大小的计算
虚函数列表在程序编译的时候已经存在;虚指针在new对象时生成,虚指针的大小与虚函数的多少没有关系,所有的虚函数都放在虚函数列表里,通过虚指针来查找!虚函数列表的地址就是对象的首地址;typedef void (*FUN)();如:father *f=new father;father ff;假如father有虚函数;则虚函数列表的地址为:*(int *)*(i原创 2016-04-11 22:23:04 · 1058 阅读 · 0 评论 -
深拷贝与浅拷贝的区别
在C++中存在构造函数,专门用来创建对象时,对对象的初始化;还有一个就是拷贝构造函数,拷贝构造函数又分为深拷贝和浅拷贝;他们的区别是:深拷贝就是,创建新的对象时,该对象自己在堆区申请一个内存空间,这样就不会出现在调用析构的时候找不到内存空间;因为如果是浅拷贝的话,所有的指针都指向同一个内存空间,当有一个对象生命周期结束后,那么该对象的内存空间要被回收,这样其他对象在析构的时候就原创 2016-04-12 22:16:09 · 984 阅读 · 0 评论 -
拷贝构造函数的调用
一直说到拷贝构造函数,构造函数在创建对象时被调用,哪儿拷贝构造函数呢??1.当用 类的一个对象初始化另一个对象时:int main(){ point A(1,2); point B(A);//用对象A初始化对象B,拷贝构造函数被调用.}2.如果函数的参数是一个类的对象,哪么在进行实参到形参的传递的时候出调用拷贝构造函数:void f(point p){}mai原创 2016-04-12 22:22:17 · 1631 阅读 · 0 评论 -
main函数外也可以调用函数
在写程序的时候,我们都知道一般一个程序肯定有一个主函数,它是真个程序的入口地址,也就是程序在这里开始执行,就像要进入一个大房子的大门,我们必须要打开这个门,才能进入整个房子里面去!并且可能我们都觉得一般的函数调用都是在主函数里面,main函数外满一般不能执行和调用函数,那么这句话对吗?函数体外面可以调用函数吗?答案是肯定的,看下面一个实例:#include using namespace s原创 2016-04-13 10:40:52 · 7683 阅读 · 2 评论 -
析构函数
当一个对象的生命周期结束后,其所占的内存就要被回收;回收资源的工作就由析构函数来完成,析构函数就是反向的构造函数:注意:析构函数没有返回值;析构函数没有参数;一个类中只有一个析构函数 ;析构函数的执行顺序与构造函数执行的顺序相反;如果在构造函数里自己在堆区申请了内存空间,那么在析构函数里就需要自己手动来完成释放!来看实例:#include using原创 2016-04-13 11:11:29 · 724 阅读 · 0 评论 -
0的作用
0在生活中随处可见,可是,它的身份确实多重的,必须的了解它的全部,下面简单介绍一下0在程序中的作用;数字0的作用:1.数字;(理所当然);2.假;(真假判断);3.代表地址;(void *) 0==nullint *p=0;//此时0代表的是地址,是所有内存的起始地址;不可对其进行操作,否则就崩溃鸟。。。。。原创 2016-04-28 22:18:26 · 800 阅读 · 0 评论 -
程序的5个区
堆和栈的区别可以用如下的比喻来看出: 使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就 走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自 由度小。 使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由 度大。堆,栈,常量,代码,静态 一个由原创 2016-05-01 11:38:19 · 1406 阅读 · 0 评论 -
new/delete和malloc/free的区别
堆区的内存管理的成员必须要面对的问题?有申请有使用有释放。俗话说:有借有还再借不难。 在C中常用malloc动态申请堆区的内存空间,比如链表的存储,链式地址解决哈希冲突,邻接表,树等等一些数据结构用到的存储就够基本上都是堆区的内存,方便管理,用起来比较自由。而C++中我们常用new来开辟一块内存空间。。。。。。因为new和malloc需要符合大众的申请内存空间的要求,针对泛型提供的,分配内存设计到分配算法和查找,此外还要避免内存碎片,所以其效率比较低下,因此有时程序猿会自己重写new原创 2016-05-01 22:25:18 · 2712 阅读 · 0 评论 -
cookie 和session 的区别
Session和cookies其实是一个非常头疼的问题。因为说它简单是因为他们都是HTTP协议的一个配置项,在servlet规范中也只是对应的一个类而已。复杂主要是表现在以下两个方面: 第一、当我们的系统大到当我们需要使用到很多cookie的时候,我们不得不考虑HTTP协议对cookie的数量和大小的限制,这是一个需要解决的瓶颈。 例如使用cookie来传递消息的时候,随着cookie的增加和访问量的增多,占用的带宽也会增大。现在一般会限制cookie的个数为20个,其总原创 2016-05-02 11:53:21 · 5707 阅读 · 0 评论 -
系统调用和库函数及API的区别
在写程序的过程中,像MFC,VC++这些编程,都会涉及到函数的调用,有库函数也有系统函数,下面看一看它们的区别!! 一、系统调用: 系统调用实际上是指底层的一个调用,就是内核提供的、功能十分强大的一系列的函数。这些系统调用是在内核中实现的。是操作系统为用户态运行的进程和硬件设备(如CPU、磁盘、打印机等)进行交互提供的一组接口,即就是设置在应用程序和硬件设备之间的一个接口层。可以说是操作系统留给用户程序的一个接口。 二、 库函数: 顾名思原创 2016-05-03 13:39:48 · 18115 阅读 · 5 评论 -
HOOK钩子机制
最近在看一些编程相关的书籍和资料,知识碰见了,就想把它记下来,以便日后能用的上,也可能只是浅显的概念!可能有错,但是有值得参考的地方,慢慢充电吧! 一、理解:钩子,顾名思义就是钩东西的,来一个比喻吧。当我们在钓鱼的时候,只要你扔出有诱饵的鱼钩(设置线程钩子或系统钩子),此后你可能会漫长的等待(HOOK等待消息或者信号的来临),但是一旦这条不幸的鱼上钩了(有消息传递,截获住了消息),它就跑不了了,这条鱼就任凭我们处置,我们可以选择放生或者报餐一顿等等(对截获的消息进行处理,调用函数,阻止消息的发原创 2016-05-03 20:44:44 · 5411 阅读 · 0 评论 -
NULL 空指针 野指针
指针是C中抬头不见低头见的东西,所以主要一下这些指针的特点,和要注意的地方!!、1、NULL指针:在系统中NULL指针被定义为:#define NULL (void *)0 NULL是一个宏定义,0是其具体的实现值,NULL的ASCII码值就是0;2、零指针:是值为0的指针,是空指针的实现。可以是任何类型的,char*,int *,void *;C++标准规定,当一个指针类型的数值是0时,认为这个指针是空的。因为0是NULL的实现(在其他标准下我们或许可以用其他的值来实现NULL,可是是1,2,3原创 2016-05-05 11:41:59 · 1464 阅读 · 0 评论 -
内存池
一、为什么要使用内存池技术呢主要有两个原因: 1、减少new、delete次数,减少运行时间,效率的考虑; 2、避免内存碎片。解释1:传统的new/delete和malloc和free的弊端: (1).分配内存时要查看内存空闲块表,根据一定的算法来分配,比如(将最先找到的不小于申请的大小内存块分配给请求者,将最合适申请大小的空闲内存分配给请求者,或者是分配最大的空闲块内存块),然后更新内存空闲块表。释放的时候,也得在空闲的内存表中加入该释放的内存,或者有必要的话,原创 2016-05-04 10:14:46 · 599 阅读 · 0 评论 -
RTTI机制与作用
一、RTTI(Run-Time Type identification),通过运行时类型信息,程序能够使用基类的指针或引用来检查这些指针或引用所指向的对象的实际派生类型。面向对象的编程语言,想C++,Java,delphi都提供了RTTI的支持。RTTI并不是什么新技术,很早就有了,他主要提供了运行时确定类对象类型的方法。最近有用到这个RTTI,对它进行了一番小研究,下面做个小小的总结吧!原创 2016-05-04 21:15:30 · 5075 阅读 · 0 评论 -
C++三种容器:list、vector和deque的区别
在写C++程序的时候会发现STL是一个不错的东西,减少了代码量,使代码的复用率大大提高,减轻了程序猿的负担。还有一个就是容器,你会发现要是自己写一个链表、队列,或者是数组的时候,既要花时间还要操心怎么去维护,里面的指针啊,内存够不够用啊,长度问题,有没有可能溢出啊等等一系列的问题等着我们去解决,还是比较头疼的。所以容器的出现解决了这一个问题,它将这些数据结构都封装成了一个类,只需要加上头文件,我们就可以轻松的应用,不用那么复杂,就连指针也被封装成了迭代器,用起来更方便,更人性化,方便了我们的编程、、、、原创 2016-05-06 17:35:26 · 59336 阅读 · 12 评论 -
函数返回局部变量问题
一般的来说,函数是可以返回局部变量的,但是要注意几种情况。 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错。但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错。因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错。准确的来说,函数不能通过返回指原创 2016-05-21 20:16:02 · 6184 阅读 · 1 评论 -
C++的初始化列表(Initilization List)
初始化类的成员有两种方式,一是使用初始化列表,二是在构造函数体内进行赋值操作。第二种我们都比较熟悉了,来看看第一种情况。 一、 为什么使用初始化列表(Initialization list) 使用初始化列表一方面主要是基于性能问题,对于类类型来说,最好使用初始化列表,为什么呢? 因为对于没有默认构造函数的类类型,使用初始化列表可以不必调用默认构造函原创 2016-05-21 22:28:07 · 4500 阅读 · 4 评论 -
iterator迭代器和指针的区别
迭代器与指针的差别:迭代器: (1)迭代器不是指针,是类模板,表现的像指针。他只是模拟了指针的一些功能,通过重载了指针的一些操作符,->,*,++ --等封装了指针,是一个“可遍历STL( Standard Template Library)容器内全部或部分元素”的对象, 本质是封装了原生指针,是指针概念的一种提升(lift),提供了比指针更高级的行为,相当于一种智能指针,他可以根据不同类型的数据结构来实现不同的++,--等操作; (2)迭代器返回的是对象引用而不是对象的值,所以c原创 2016-05-05 22:00:47 · 30945 阅读 · 10 评论 -
dynamic_cast、static_cast、const_cast和reinterpret_cast的区别
C++的类型转换分为两种:隐式转换和显示转换。 一、 对于隐式转换,就是标准的转换,在很多时候,不经意间就发生了,例如int和float加法,int类型就会被隐式转换为float了,这种称为升级转换。还有就是把等号右边的值转换为左边的类型,再赋值。还有类变量作为参数传递给函数:show(5);//这里也发生了隐式转换,将5转换为B类型的(B)5;B b=10;//也是OK的,发生了隐式转换,除非加上explicit;二、显示转换:在C++中有四个类型转换符:static_cas原创 2016-05-04 20:48:21 · 5080 阅读 · 0 评论 -
什么函数不能申明为虚函数的问题
虚函数可以说是C++中一个十分重要的概念,正因为虚函数的存在,它通过动态联编(迟联编译)让我们实现了多态!虚函数必须是类的非静态成员函数,前面+virtual关键字修饰的就是虚函数;它是在程序运行(强调动态)的时候匹配各个对象合适的成员函数。定义了虚函数后可以再派生类中重新定义该虚函数,但是要求参数个数,类型,返回值(可以是父子之间的不一致)一致。以实现统一的接口,如果没有重新定义该函数,则继原创 2016-04-11 18:29:10 · 2175 阅读 · 0 评论 -
虚析构的作用
为什么在写类的时候,析构函数要定义为虚函数呢?主要作用:是为了防止,在实现多态的时候,在用父类的指针操作派生类对象后,在析构的时候只回收了基类的资源,没有析构派生类函数;这样造成了内存的泄漏!!来看一段代码示例就懂了:#include #include using namespace std;class father{public: int a ; double b;原创 2016-04-10 21:11:00 · 1174 阅读 · 0 评论 -
类里的对象指针与函数指针
类里面经常会遇到函数指针与对象指针的问题,并且经常容易出错,所以整理一下,以备后用!!#include using namespace std;class father{public: void foo() { cout<<"this is the foo"<<endl; }};class son :public father{public: void fool()原创 2016-04-10 11:44:00 · 1580 阅读 · 0 评论 -
重写 重载 隐藏
C++中有很多概念,很容易混淆,下面主要来说一下重载,重写和隐藏的区别:重载:overload --函数名一样,函数的参数不同(包括参数的个数,参数的类型),返回值没有要求:重写:override --函数名称,参数,返回值一样(返回值仅限父类和子类的时候不一样);隐藏:hide--重载的函数放在子类和父类中就会形成隐藏:#include using namespace std原创 2016-04-10 11:30:12 · 639 阅读 · 0 评论