C++是面向对象语言,其语言特性同C有很多地方看起来很像,但实际上是不一样。C++作为面向对象的语言,它具有面向对象的特点,如具有重载、覆盖、隐藏等特点。这一节重点讲一下C++特有的一些性质及与C的不同,避免在使用过程中加心混淆。C++实现面向对象同JAVA面向对象还是有很大不同的,因为面向对象只是一个软件工程概念,而语言它是一个实现领域问题。C++中是如何实现面向对象的一些特征呢?

【1】面向对象的重载、覆盖和隐藏。 首先重载,对C++来说,因为它有全局函数,与JAVA不一样,JAVA没有全局函数。JAVA里面都是类,就是main函数也是类的一个成员函数。因此,对C++来说重载一定注意它发生在哪?谁跟谁同名参数不同算重载,需要定义一个作用域问题。这个作用域就是如果是类成员函数就都是类成员函数,如果是全局函数就都是全局函数。不在同一个作用域内不是重载,如下图所示:

C++/C语言深度剖析(4)_休闲

如果在成员函数中引用全局函数print怎么用呢?使用: : print(……..)。重载的一个重要特征是函数名字相同,但参数不同(类型,个数)。那么显然可以想到的是因为C++支持继承,继承的父子类中函数名字相同参数相同算什么呢?这就是覆盖。所以覆盖与重载的一个最大区别就是不同范围,也就是父子类中,并且参数是相同的。通常覆盖函数的基类中加上virtual函数。覆盖这个特性跟JAVA是有一定区别的,JAVA默认特性与C++中都加上virtual是相同的。如果没有使用virtaul关键字就会产生一个新的特性就是隐藏,隐藏有一个很难理解的就是如果没有virtal的同名函数,如果父子类中是参数不同的。按道理来说子类会继承父类的所有PUBLIC成员函数,那这个时候对子类来说也就是具有同名但参数不同的函数,那这种情况下算什么呢?算隐藏。如下图所示:

C++/C语言深度剖析(4)_职场_02

前面讲到重载,重载还可以发生在运算符上,常用的++ + = 都可以被重载,这时参数就是运算子。重载运算符不是无节制的,有些不能如. :: ? sizeof 、 # @ $等。并且内部类型如int也不能重载。

【2】面向对象的构造、析构函数及拷贝构造函数 编译器默认会创建一个缺省的四种函数。这几种缺省函数虽然在一定条件满足使用,但如果不正确的使用会带来一定的风险,如缺省的拷贝构造函数和缺省的赋值函数都是采用位拷贝,会带来内存上的丢失,如这个类中带有指针的成员变量。如下图所示:

C++/C语言深度剖析(4)_职场_03

如上图所示,当进行重载构造函数或者有多种继承下的构造函数里,需要对成员变量进行初始化。初始化方法就是如B: : B (int x,int y):A(x)。建议非基本数据类型都采用这种方式进行初始化。如果不想实现拷贝构造函数和赋值函数但也为了避免它人误用,可以将它们设置为私有函数如下图所示:

C++/C语言深度剖析(4)_C语言_04 

【3】面向对象的继承 继承在C++中与JAVA不一样,继承它还分三种不同的继承方式,不同的继承方式决定了子类能否自动具有父类哪些成员函数与成员变量,但有三种函数是不能被继承的,就是构造函数、析构函数、赋值函数。因此,对构造函数需要在子类初始化表中进行初始化,对析构函数通常使用virtual进行重写,对赋值函数需要对基类进行调用。如下图所示:

C++/C语言深度剖析(4)_C语言_05

继承与组合不一样,从面向对象的概念就要严格区分,如人可以分男人、女人,但人是由头、手、足等组成的。

【4】C++与C混编 C++具有重载机制,当C++编译器处理函数时会重新生成一个新函数名称,如eat(int fish)会变成eat_fish(),而C没有重载机制,如下图所示:

C++/C语言深度剖析(4)_休闲_06

因此不同编译器对C++与C对函数处理方式的差异将导致生成的字节码对象定义错误。所以如果C++要使用C函数,那就必须使用关键字extern 来指定。如下图所示:

C++/C语言深度剖析(4)_C语言_07

【5】inline 内联, 内联与define不同的是define是在编译前替换,内联是将函数体直接放在符号表,避免函数创建的开销。内联必须放在函数定义前才有效,声明上放无效。在C++中如果定义文件写在类的声明文件中就自动是内联函数。但通常不建议这样做。还是在定义体前加inline比较好。如下图所示:

C++/C语言深度剖析(4)_C语言_08

【6】main函数原型的不同,main函数在C和C++中经常看到各种各样的写法,看起来似乎这些写法都能编译通过还能正确运行,这是因为这些差异是由标准差异引起的。在C89是void main()是可以接受,但在标准c99中是int main(void) 或者int main(int argc,char *argv[],char *engv[]) ,其中一个表示入参,另一个表示环境参数。如下图所示:

C++/C语言深度剖析(4)_C语言_09

【7】C++与C的一些异同点,C++作为C的超集,听起来好像C的东东在C++中都可以直接用,实际上这是有错误的,C++是一门新的语言,只能说它跟C是近亲关系,它的很多处理方式都是与C不同的,而且也不是说C的方式它也接受,而是不接受,常见有以下几点差别比较大的:

1)函数 标准C/C++都要声明后定义,并且声明时函数参数可以不写名称,但类型一定要写,如这样声明int translate(float, float ,float)。如果没有参数如func()在C中表示可变参数,而在c++中表示无参数,所以通常C++都是func(void)。 如果没有返回值,默认C中返回int ,C++中一定声明,如果没有返回值,写上void。这也是一大区别。另外C++函数可以在声明时进行初始化。初始化顺序是从右到左。

2)true/false 在C语言中不是关键字,但在C++中则是。如在C++中可以 int a =1 ; if(a==true){};

3)变量,在C中变量都必须在函数体前面定义,通常称之为声明。而在C++中则不一样,则是需要时可以声明,这里声明其实也就是C++中的定义。也就是说在C++中对变量不再有声明之说,除了extern关键字之外,其它都是定义。因此变量定义可以在任何地方定义。如for(int i =0;i<5;i++}{int a = 3;}

4)引用,引用是C++独有的,但void类型没有引用。空指针有引用。C本来没有const但后来引入了const用法比C++少。主要是没有关于类的修饰。voilate同const相反,需要注意的是正确使用voilate可以防止CPU优化。

5)类型转换 指针类型不能自动转换,这一点是共同的,如 int a =10; int *p =a;这是错误的。C++中除了C的基本转型之外,还支持如float a = float(200)。另外C++还使用如下四种cast进行强制转换,分别是static_cast(static_cast可以消除编译器告警,如int i = 0x7fff; long l =static_cast&lt;long>(i)) , const_cast(可以将一个const转为非const,或一个voliate转为const), reinterpret_cast(这个可以在任意类型之间进行转换),dynamic_cast.

6)struct C++中struct与类基本一样,除了全是public之外,因此struct 中可以定义函数。不过一般不建议。