分享

C 基础知识

 cntagu 2016-04-23


给大家补习下C++基础知识

类的数据类型指的是:类是成员变量和过程的聚合体,通过该聚合体,类得以完成将对象进行建模的任务


面向对象编程中最富挑战性和创造性的工作就是类的设计,同时,面行对象编程也是以类的设计为基础的


面向对象设计和面向对象编程的另外一个重要内容是关系:类与类之间,对象与对象之间

在return语句中,返回值i:
传值返回:将i先拷贝的临时存储空间,调用着获得的是i的一个副本
 引用返回:将i的值直接拷贝到接受的空间中(调用者)

使用引用返回的一个好处是:如果一个函数以引用返回,则这个函数调用可出现在赋值语句的左边


因为使用引用返回的函数返回的是一个实际单元,必须保证函数返回时该单元仍然有效(不能是临时变量)

int &  f()

{

    int i;

    return i;

}    //错误



但是:

int f()

{

    int i;

    return i;

}    //正确

关键字inline在函数生命中用来请求将该函数以内联方式展开,也就是说,在每个调用该函数的地方插入该函数的实现代码


这个特定和宏很类似。避免了开销。但是如果函数很大,或者使用在很多地方,程序的可执行代码变得很大

与宏不同的是,内联函数是通过编译器完成的。要考虑语义(宏不检查语义)


所有没有默认的参数都放在参数开始部分,接下来是具有默认值的参数,穿插着不行!!


重载:能通过参数个数和类型区别


C++中加extern c{} 的原因是为了屏蔽他们在编译中生成的符号的差别


void (double,int)和 void (int,double) 是重载函数

但是返回值不一样不是重载函数  :int s(int) 和 double s(int)

C++中struct 传递是按值传递:

看下面一个例子:


结果:


为了验证结果,同时和引用传递对比,下面修改一下:


修改后结果:


那下面这种情况:


先看看下面的情况再说 :


来看结果:


总结一下:

在C++中,结构体是以传值的方式进行的,通过例子1和例子2我们可以看出来,同样,虽然例子3和例子4达到的结果相同,但是同时也从侧面支持了我们研究结果的正确性

例子3是结构体传递,但是它的变量确实没变,之所以最终的值发生了变化,是因为结构体的变量的指向的值发生了变化。

也说明了引用是最保险的办法


函数重载和缺省变量结合在一起的时候小心一点:

看下面例子有错没有:

结果:


知道了吧,如果这样重载的话,编译器找不到你要调用的函数,不知道你要调用哪一个 ?就想两个人都叫宁华,一个男的,一个女的。他们两个明显属于不同的个体,但是如果你不加细分处理的话,仅仅是叫宁华,他们会不知道叫的是谁,当然其他人也不知道,所以我们应该从其他地方区分,例如,叫女宁华,就一女的,叫男的,就男的。这不是说宁华是两性的,也不是说她会变性,只是区分两个不同的个体而已

大家对C语言的链表已经熟悉的一听说到华仔就知道是女的,一听说小雌就知道是男的一样。那么C++的链表呢?

虽然本质没有什么差别,但是还是熟悉一下吧,另外熟悉一下C++内存分配问题,下面一个例子代过:




下面让我们来看看,像王小贱一样贱的知识点:例外处理

这一块比较简单,条条框框套进去,然后正常编程就行。一个例子搞定:


C++支持无名联合,即没有名字的联合,这里我们介绍一下,同时要注意联合的特性:通过例子说明:


结果:


对比一下下面这个特别是结果:

结果:


大家一定会发现:为什么给两个变量赋值顺序不同显示的不同,这个不解释:常识!

无名联合的成员可以当作普通变量使用。

在相同的作用域之内,不能定义与无名联合中的成员同名的变量。

并且::不无定义以无名联合为数据类型的变量!!

从一定程度上来说,无名联合和{}更像!只是稍微变量作用域的区别。

下面再看一个支持观点的例子:


看结果:


一目了然,不解释,本质上面已经说的很清楚

大家对结构体已经很熟悉了吧!现在我们看看它另类一点的用法。此用法和小雌一样雌!

下面这个例子的错误很常见,大家注意一下:


这个例子不再写输出了,也不注释掉出错的两行,演示正确的了,大家仔细看看:

大家要注意一点:f_ptr已经不是指向float的指针,而是指向类C中的float成员。这样限定是不是在安全上或者保护变量方面有很大好处

因为C++和C语言有丝丝区别,而且结构体里面加上函数指针,我们用一个例子 来搞定它:


C++基础知识就这些,下面看一下编程的常见错误:

1,区分using指令和using声明:

     using namespace + 命名空间               ==========>             using  指令

     using + 命名空间::命名空间内元素   ==========>             using  声明

2,在使用标准输入/输出流进行任何键盘输入和视频输出之前,必须包含:

       #include 

      为了使用特性,通常这样:

       #include

       using namespace std;

3,using namespace std 和 iostream.h 等*.h不能共存。如果是旧版本,就用*.h,不能混用,否则出现错误

4,<和>>只能输出一个数据,或者输入一个数据,如果想多个,每个后面前面都要有<或者>>

5,操作符<>

     cout < n="">< m=""><>

     是错误的,应该这样:

     cout < (n="">< m)=""><>

6,要是用带参数的操作符,必须包含头文件iomanip.

7,操作器作用于数据流之中,除了控制域宽的操作器(控制域宽的操作器在输出了一个字符串或数字后自动清0)之外,其他所有操作器所造成的影响具有持久性。不要误认为在语句结束后所有输入输出设置都恢复为默认值

8,混用C和C++的输入/输出功能,可能会导致不可预测的错误,使用函数:

  ios::sync_with_stdio()

  可以消除这种隐患

先看这种:


这样做是很危险的,下面的是安全的:


9,文件操组,必须包含头文件fstream

10,强制类型转换放在需要转换的数据类型包含在<>而不是圆括号内:

        static_cast(int)(26)             //ERROR

   static_cast(int)<26)           >

        static_cast(<26>        //ERROR

        static_cast(26)           //RIGHT

        <>内是被最终要被转化成的数据类型

        C++有四种数据类型转换:

        static_cast<>()把一种数据类型转换成另一种数据类型

        const_cast<>()把数据类型的常量性去掉

        reinterpret_cast<>(),用来改变指针类型,谨慎用

        dynamic_cast<>()用于继承层次中的类型转换

11,C++允许变量随时使用,随时定义。但是作用于的范围显得非常乱,一定要注意:

     特别是for循环中的定义的临时变量,只在for循环中有效

12,与文件操作相关的open()函数接受C风格的的字符串

       string s = 'myfile.dat';

       ifstream infile;

       infile.open(s);

      是错误的,应该为:

      ifstream infile;

      infile.open('myfile.dat');

      或者:

       string s=“myfile.dat';

       ifstream infile;

       infile.open(s.c_str());

12,当用操作符<>

13,赋值操作符可用于string类型。操作符右边可以是string字符串、C风格字符串或字符。但左边必须是string字符串:


同理 += 操作符也一样。左边只能是string字符串,右边可以是string字符串,C风格的字符串、或是一个字符

+操作符也一样,但是还要注意一点,+ 操作符的右边的两个不能都是字符串。但是可以都是string字符串,可以一个C字符串、一个string或者一个string、一个字符

string s1 ,s2 = 'W.C.',s3 = 'Fields';

s1 = s2 + s3;                                          //OK

s1 = s2 + 'Fileds';                                 //OK

s1 = 'W' + s3;                                        //OK

s1 = 'W.C.' + 'Fields';                            //ERROR

14,对于string类型的下述函数:erase、insert、replace和substr等,传给它们的第一个参数不能大于或等于字符串的长度。

       超出长度范围的错误长度将导致程序异常终止,尽管通过例外处理可以捕捉到这些错误

15,调用未声明的函数是非法的。每个系统函数也必须线声明,通常是包含相应的标准头文件

16,不为函数指定返回值是错误的

17,main函数的下面两种定义是可移植的:

        int main(){}

        int main(int argc,char * argv[])

18,因为采用引用返回方式的函数返回的是实际的单元,所以必须保证该单元在函数返回后依然存在

19,关键字inline用于函数声明而不是函数定义:

下面程序是错误的:


因为内敛函数swap只在它定义的地方到文件结束才可见,所以它对main来说是不可见的,因此编译器将告之找不到swap函数

20,默认参数应在函数声明而非函数定义中给出:

下面的代码是错误的:


看看哪出错了,出的什么错误:


看吧,不认识它,应该这样来写:


21,对于使用动态方式分配的对象,在该对象超出其作用域之前不使用delete将其删除,是一种不良的编程习惯:就是在一个作用于中动态申请,在另一个作用域中删除(不一定)

有一种落差是,你配不上自己的野心,也辜负了所受的苦难

编程学习4群 546982836

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多