C++再修(一)————通过一个头文件,来讲解整个程序的部分概念

这个是候捷版本的C++面向对象高级开发的课程,感觉不错,记下来

头文件的写法:(防卫式的声明)

头文件有一种非常正规的写法,一定要学习起来:

#ifndef _COMPLEX_
#define _COMPLEX_
          .
          .
          .
          .
          .
#endif

一个头文件先这么写(如上),为什么要写这个东西呢?因为有很多程序,要用到你这个头文件,或者你自己也可能用到,如果有很多头文件,用户在调用(include)的时候,会出现到底先调用那个头文件的问题,头文件很多的话,会很难排,所以,这种防卫式的声明,非常管用。大致原理是:但机器执行的时候,一读到第一行代码告诉编译器说:一进来,如果不曾经定义过“_COMPLEX_”这个东西,那么就把它定义出来,然后就继续执行下面的内容,所以,当程序第一此调用(include)这个头文件的话,很容易就被定义好了,在同一个函数里面,第二次再(include)的时候,因为“_COMPLEX_”已经被定义好了,就不会再进来了,下面的代码也就不会再被执行了,这样就可以避免头文件被重复引入。

Header(头文件)的布局:

那么下面就开始写中间的内容部分,先写第一部分:

class的声明(declaration):

任何一个class一定有一个“头”(class head),这里面你就需要去设计,我的复数应该具备什么样的数据,我的应该准备什么样的函数,才能够满足使用复数的人的需求,比如说,大家都知道数学里面有个共轭复数,那我就应该在这里写一个共轭复数这样的函数出来。那结果就是这样

class complex  /*............................<-class head,“complex”也是类的名称*/

/*................................class body如下*/
{
public:
    complex  (double r = 0, double i = 0)
       :    re  (r),  im  (i)
   {  }
    complex&  opeartor  +=  {const complex&};
    double  real () const { return re;}
    double  imag () const { return im;}
private:
   double re, im;/*复数里面有实部和虚部,那我就人为的来定义一下*/ 

   friend complex& __doapl (complex*, const complex&)
}; 

在函数当中的用法为:

{
    complex  c1(2,1);
    complex  c2;
    . . .
}

inline函数:最好将大部分函数都写成inline的形式,上例中“{ return re; }”“{ return im;}”构成了inline函数,函数若在class body内定义完成,便自动成为inline函数,如果在外头定义,就不是inline函数了。但是,要注意的是,如果函数太过于复杂,就没有办法inline了。比如说,就这两个函数,我们设计成inline函数,但具体是不是按inline来编译,那就是编译器的事情了。

如果是在非class body下定义完成的inline函数,举例如下:

inline double
imag(const complex&  x)
{
    return  x.imag  () ;
}

在一个class body中,很明显可以区分为几大段,用什么来区分呢?就是“public”(公开的,被外界所看的到的)和“private”(只有我class里面才可以看得到)。那什么东西才可以放到“private”里面呢?当然是数据的部分,因为我们需要的数据是封装起来的,不要被外界任意看到。那函数部分呢?函数也分两种,一种给外界用的,一种来处理自己私人的事情,在这个例子里面,大部分函数都是要被外界所使用的,所以,所有函数我们都放在"public"里面。这些段落是可以交错的,想到一段写“public”,再想到一段写“private”无先后顺序,或只能写两段。

那这有什么影响呢?

举个例子:

{
    complex  c1(2,1);
    cout  <<  c1.re;
    cout  <<  c1.im;
}

这样写就是错的,因为“re”和“im”定义在“private”里面,是不会被读取出来的。

而这样写:

{
    complex  c1{2,1};
    cout  <<  c1.real();
    cout  <<  c1.imag();
}

是可以的,因为调用的是"public"里面的“real”和“imag”函数。

最后总结一下,我们把“public”“private”他们所形成的这个区域,称为:“access level ”访问级别。

如果你写的函数打算被外界调用,那你就放在“public”里面,如果你写的函数,只打算在内部被运用,没打算被外界调用,那你就放在“private”

在C++里面,如果你想创建一个东西(就是对象),有一个函数会自动被调用起来,不需要人工调用,自动起来。这就叫做构造函数,比如,下面这个例子:

{
    complex c1(2,1);
    complex c2;
    complex * p = new complex(4);
    . . .
}

这三个都在创建对象,创建对象的话,一定有一个函数在里面。

这种构造函数的写法很独特,它的函数名称,一定要跟类的函数名称相同,才能够叫做构造函数,并且,它可以用有参数,在class body 里面,complex头文件定义部分。自然想到实部和虚部两个部分来定义。

  complex  (double r = 0, double i = 0)
       :    re  (r),  im  (i)/*这行是初始化,只有构造函数才有,表示把r分给re,把i分给im*/
   {  }

其中“r=0”和“i=0”都是默认实参(default argument)。就像上面的那个c1有指明参数,那就是用它指明的,c2没有指明的参数,那就用class body 里面定义好的默认实参好了

充分利用每个函数的特点,是判断编写是否大气的标志,上面就是大气的一个典范!

构造函数可以有很多个-overloading(重载),比如说你设计一个类,等待外界来创建一个对象,创建对象的时候要怎么创建?假设你有三种设计思路,那你就写出三个构造函数,C里面是不允许这样做的,但C++是允许的。相同函数名称,却不止一个,这个就叫做overloading

举个例子:

void real(double r)   ( re=r;)

这样定义也是可以的,虽然,会跟class body 里面的real冲突,它们机器码不一样。

但如果是这种情况下:

complex  (double r = 0, double i = 0)
       :    re  (r),  im  (i)
   {  }
complex   ()    :   re(0) , im(0)  {}

因为重名,会出现冲突。

函数重载,一般多发生在构造函数里面。

* class template(模板)

在上面的class中,实部和虚部是人工定义为double值,那我如果要设计另外一个复数,它里面的类型是浮点数(float),或者是整数,怎么办?可上面已经写死了,不能动了,那就只好再把原来的程序原样敲一遍,只到定义实部和虚部的部分,改一下,这样写太麻烦了,于是,C++的设计者,就发明了针对类似这种情况的东西————class template(模板),写成:把实部和虚部的位置不要先写死,我想要以后用的时候,我再指定

template<typename T>/*提前告诉编译器,T是一个type*/
class complex
{
public:
    complex  (double r = 0, double i = 0)
       :    re  (r),  im  (i)
   {  }
    complex&  opeartor  +=  {const complex&};
    double  real    ()   const  {  retrun  re;  }
    double  imag   ()   const  { return  im;}
private:
    T  re,  im;/*T的意思可以理解成告诉编译器:我现在是什么类型,我还没有决定呦!*/

    friend  complex& __doapl  (complex*,  const  complex&)
};

在函数当中的用法为:

{
    complex<double>  c1(2.5,1.5);
    complex<int>  c2(2, 6);
    . . .
}
时间: 2024-10-10 09:05:54

C++再修(一)————通过一个头文件,来讲解整个程序的部分概念的相关文章

&lt;06&gt;变量使用前易犯错误总结+if语句介绍及基本格式+if-else语句及嵌套+if语句的高级用法+if语句的使用注意点+arc4random_uniform 函数导入一个头文件&lt;stdlib.h&gt;+

1)变量要初始化 -1 0  ,或者1 依据程序而定 ---------------------------------- if语句介绍及基本格式 分支语句结构 1)if 格式: if(表达式/常量/变量){ 语句块1; } 原理: 1)先计算小括号中的表达式的值 真(1) 会执行 大括号中的语句 假(0) 不会执行 大括号中的语句 2) switch 1 #include <stdio.h> 2 3 int main(int argc, const char * argv[]) { 4 5

控制流程——学渣C语言再修之路

C语言的控制流程是基础中的基础,几乎没有程序不用到选择和循环控制的,今天又来看这些内容,以求入门. 选择结构: 只有一个选项:这个肯定很easy啊,就是 if(expression){ Statements: } 这里就是要注意代码的简单易懂,expression一定不要写的太复杂,判断条件很多时就可以分开来写,不要写晦涩的代码. 两个选项:这个就是 if(expression){ Statements: }else{ Statements: }没有什么好说的. 其实这里可以用三目运算符来代替

unix高级编程中的一个头文件 apue.h 与一个差错文件error.c 的内容

在查看unix高级编程中的代码时,如果我们编写书中的代码,发现一般都会报错,这是因为作者在写这本书时,他自己编写了一个头文件,跟一个差错处理文件,出来处理他自己的代码错误信息: 下面我们来看下代码的内容: 我实现第一个代码,关于文件的打开,实现 ls 命令的代码: #include "apue.h"#include <stdio.h>#include <dirent.h> int main(int argc, char *argv[]){ DIR *dp; st

如何在VC6.0下用pthread.h这个头文件

如何在VC6.0下用pthread.h这个头文件 1.下载PTHREAD的WINDOWS开发包 pthreads-w32-2-4-0-release.exe(任何一个版本均可) http://sourceware.org/pthreads-win32/,解压到一个目录. 2.找到include和lib文件夹,下面分别把它们添加到VC++6.0的头文件路径和静态链接库路径下面: a).Tools->Options,选择Directory页面,然后在Show directories for:中选择I

C C++每个头文件的功能说

C/C++每个头文件的功能说明 传统 C++ #include <assert.h> //设定插入点 #include <ctype.h> //字符处理 #include <errno.h> //定义错误码 #include <float.h> //浮点数处理 #include <fstream.h> //文件输入/输出 #include <iomanip.h> //参数化输入/输出 #include <iostream.h&g

1.在VC编译器下面为什么每个头文件以及源文件都要包含“stdAfx.h”,那么stdAfx.h中到底存放了什么,用来做什么?

我们知道在windows平台下面很多的文件后缀名中都含有Afx,其实Afx是微软公司的一个技术研发团队名称,vc下的“stdAfx.h”和“stdAfx.cpp”文件就是有他们所研发出来的,为什么要这么做呢,原因是当我们在一个工程下面建立多个头文件和源文件并且这些头文件和源文件 都包含了系统(比如windows.h)文件时那么在编译阶段就会发生非常庞大的代码展开(因为系统文件一般都比较庞大)在这些每一个包含了系统文件的头文件和源文件中去多次展开无疑是效率上的灾难,那么有没有办法只进行一次展开呢,

ubuntu下安装Firefox后点击firefox没有为可执行文件文件类型安装应用程序

http://blog.csdn.net/pipisorry/article/details/39480227 ubuntu上安装 firefox 和 Chrome 与 Opera 不同,Mozilla 的官方网站提供的 Firefox for Linux 并不是 deb 或 rpm 这样的安装包,而是一个 tar.bz2 的压缩文档.许多人看到 tar.bz2或 tar.gz 这样结尾的文件,自然而然地会以为这又是什么"源代码编译安装"?太痛苦了!其实不是,把它下载下来,解压缩,你会

LaTeX-WinEdt 编辑器和 PDF 文件的 Acrobat 11 程序关联

WinEdt 编辑器和 PDF 文件的 Acrobat 11 程序关联 CTeX 套装 2.8 版本以后,也就是09年9月以后的版本加入了SumatraPDF程序,将PDF文件与Acrobat程序取消了关联,改用了SumatraPDF程序显示,也就是在WinEdt编辑器的面板上,点击"Acrobat Reader"按钮后用SumatraPDF程序打开关联的PDF文档,这可能涉及到版权啥的原因,在此就不多说了. 我们可能还是习惯使用Acrobat程序查看和标记PDF文档,因此介绍一下如何

分批读取文件中数据的程序流程及其C代码实现

一.概述 在实际的软件开发项目中,经常需要处理大量的文件.某些文件中包含了相当多的数据记录数,如作者本人参与过的项目中,一个文件中有好几十万条记录.如果一次性将多条记录读入,则会花费大量的处理时间,且占用大量的内存. 为此,要求对于包含大量数据记录的文件进行分批读取操作,即每一轮读取一定数目的数据记录,待将这些记录处理完成之后,再读取下一批数据.本文介绍分批读取文件中数据的程序流程,并给出了C程序实现. 二.总体程序流程 实现分批读取文件中数据的程序流程如图1所示. 图1 实现分批读取文件中数据