C++程序设计

    C++程序设计html

  以前学过C++课程,可是时间有点久,忘了不少,这里作一个简单的回顾。前端

  网站推荐: C++在线编译器node

  学习C++以前,您能够先了解C语言ios

  c++的扩展名通常为cpp(cplusplus)。c++

  补充: 这里介绍了如何编译和执行C++文件,即通常须要下面的步骤:程序员

  1. 在文件的外面shift + 右键单击,选择cmd打开文件(cpp的外层文件)
  2. g++     文件名.cpp      -o       test
  3. test 

  经过这三步就能够编译C++文件了。编程

  注意:1. 每次若是修改了文件,都须要在g++ 文件名.cpp -o test来从新编译文件获得文件名.exe可执行文件,而后在执行便可。这时新的可执行文件就能够覆盖旧的可执行文件。windows

       2. 在notepad++中的设置-> 语言设置中将语言设置为C+数组

       3. 若是使用mingw进行编译,那么颇有可能生成了exe文件并执行时会闪退,这时,咱们须要添加头文件 #include <windows.h>,而后在main函数的return语句前添加system("pause"),这样就能够正常看到结果了。
安全

 

  上面说的使用g++这种方法在windows下必须下载mingw(Minimalist GNUfor Windows),即window系统下使用的编译机器,这样,咱们进行编译的时候须要使用命令行操做;

  而若是使用dev c++、visual c++、visual studio,这些是GUI的,属于IDE,即比普通的mingw多了更多的功能,能够进行debug、项目建立等等,而显然若是使用mingw就只能经过提示来查找错误。

 

     

    如上所示,在vscode中,咱们能够轻松的使用内置命令行经过相关命令实现运行,注意,这里的start不只仅是能够运行一个exe文件,这里的start还能够打开一个文件,好比start ./test.cpp 就会把test.cpp这个文件默认在一个编辑器中打开。

 

 

 

 

第一部分: 面向对象程序设计概述

1 面向过程的程序设计和面向对象的程序设计

  面向对象程序设计面向过程程序设计有着本质的区别。

  面向过程程序设计是以功能为中心,数据和操做数据的函数(或过程)相分离,程序的基本构成单位是函数

  而面向对象程序设计是以数据为中心,数据和操做数据的函数被封装成一个对象,与外界向分隔,对象之间经过消息进行通讯,使得各对象完成相应的操做,程序的基本构成单位是对象

简单地说,面向过程的程序设计是以函数为基本构成单位; 而面向对象的程序设计是以对象为基本构成单位。

   

 

2. 为何C++是面向对象的程序设计? 面向过程的程序设计有什么不足呢?

  • 面向过程的程序设计是围绕功能进行的,用一个函数实现一个功能。 全部的数据都是公用的,一个函数可使用任何一组数据,而一组数据又能够被多个函数所使用。 当程序规模较大时、数据不少时,程序设计者每每感到难以应付。 因此面向过程的程序设计每每只适用于规模较小的程序。
  • 面向过程的程序设计其数据是公有的,谁也没有办法限制其余的程序员不去修改全局数据,也不能限制其余程序员在函数中定义与全局数据同名的全局变量,故很不安全。
  • 因为面向过程程序设计的基本单位是函数,因此代码重用的最大粒度就是函数,对于今天的软件开发来讲,程序修改的难度很大。

基于以上面向过程的程序设计的不足,人们提出了面向对象的程序设计。

 

 

 

 3. 面向对象的编程思想

(1)客观世界中的事物都是对象(object),对象之间存在必定的关系。

(2)用对象的属性(attribute)描述事物的静态特征,用对象的操做(operation)描述事物的行为(动态特征)。

(3)把对象的属性和操做结为一体,造成一个相对独立、不可分的实体。对象对外屏蔽其内部细节,只留下少许接口,以便和外界联系。

(4)经过抽象对对象进行分类,把具备相同属性和相同操做的对象归为一类,类是这些对象的描述,每一个对象是其所属类的一个实例。

(5)复杂的对象可使用简单的对象做为其构成部分。

(6)经过在不成程度上运用抽象的原则,能够获得通常类和特殊类。特殊类能够继承通常类的属性和操做,从而简化系统的构造过程。

(7)对象之间经过传递消息进行通讯,以实现对象之间的动态联系。

(8)经过关联表达类之间的静态关系。

 

4. 面向对象的基本概念

  1. 对象

  从现实角度来讲, 现实世界中的任何一个事物均可以看作一个对象,如汽车、房屋等,这些都是有形的;又如文章、计划等,这些都是无形的。对象有大有小,如一个军队是一个对象,一个蚂蚁也是一个对象。

  任何一个对象都具备两个基本要素:属性和行为。属性是用来描述对象的静态特征。行为是用来描述事物的动态特征。 如一我的是一个对象,其身高、性别就能够看作属性,其能够走路、说话、打球就能够看作其行为。

  且在对象之间必定要有联系,如电视这个对象被人这个对象按了一下开机按钮, 电视这个对象就开机了,这就是对象与对象之间的联系。

  总结:对象具备表示静态特征的属性和表示动态特征的行为,对象与对象之间须要传递信息来联系。

  

  2.

  类是对客观世界中具备相同属性和行为的一组对象的抽象,它为属于该类的所有对象提供了统一的对象描述,其内容一样包括对象和属性。

  那么什么是抽象呢? 抽象就是指忽略事物的非本质特征,只注意那些和当前目标有关的本质特征,从而找出事物的共性。好比人就能够看作一个类,即人类,其中他是世界上全部实体人如张3、李4、王五的抽象。

  总结:类是对象的抽象,而对象则是类的实例,或者说是类的具体表现形式。

  

  3. 封装

  平常生活中的封装不少,如录像机,从外面来看他就是一个黑盒子,在他的表面有几个按键,而其内部的电路板和机械控制部件在外面是看不到的。

   这样作的好处在于大大下降了人们操做对象的复杂程度,使用对象的人彻底不须要知道对象内部的具体细节,只须要了解其外部功能便可自如地操做对象。

  在面向对象方法中,所谓“封装”即包括两方面的含义:(1)用对象把属性和操纵这些属性的操做保证起来,造成一个基本单位,各个对象之间相互独立,互不干扰; (2)将对象中某些部分对外影藏,即影藏其内部细节,只留下少许的接口,以便于和外部联系,接受外界的消息。 

 

   4. 继承

  所谓继承是特殊类自动地拥有或者是隐含地复制其通常类的所有属性和操做。

  集继承具备‘是一种’的含义,如卡车“是一种”汽车,“轿车”是一种汽车,两者做为特殊类继承了通常类 --汽车类的全部的属性和操做。

  咱们也能够一个特殊类继承多个通常类,这就是多继承的概念。如继承了“销售”类和“经理”类就是“销售经理”。

  C++提供的继承机制,就能够很方便的在一个已有的类的基础上创建一个新类,这就是常说的“软件重用”的思想。

 

  5. 消息

   对象之间经过消息进行通讯,实现了对象之间的动态联系。 在C++中,消息就是函数调用

  

  6. 关联

  关联是两个多多个类之间的一种静态关系。 如一个教室类能够管理一个学生类

 

  7. 组合

  组合描述的类和类之间的总体和部分之间的关系。如汽车和发动机之间的关系就是组合。 其实,组合是关联的一种。

  

  8. 多态性

  如某个董事长出差,他把这个消息告诉了身边的人: 妻子、司机、秘书。 这些人听到以后会有不一样的反应:他的妻子给他准备行李、秘书为他确认考察地安排住宿、司机会为他准备车辆。 这就是多态

  在面向对象方法中,所谓多态性是指由继承而产生的相关而不一样的类,其对象对同一个消息会作出不一样的响应。 

      

 

第二部分:基础知识

1. C++是什么?

C++ 是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言,支持过程化编程、面向对象编程和泛型编程。

C++ 被认为是一种中级语言,它综合了高级语言和低级语言的特色。

C++ 是由 Bjarne Stroustrup 于 1979 年在新泽西州美利山贝尔实验室开始设计开发的。C++ 进一步扩充和完善了 C 语言,最初命名为带类的C,后来在 1983 年改名为 C++

C++ 是 C 的一个超集,事实上,任何合法的 C 程序都是合法的 C++ 程序。

注意:使用静态类型的编程语言是在编译时执行类型检查,而不是在运行时执行类型检查。

      

2. 基本结构

#include <iostream>
using namespace std;
// main
int main () { cout << "朱振伟"; return 0; }

 

  • C++定义了一些有用的头文件,咱们必须引入<iostream>, 不然相似cout和cin 的输入输出都是不可用的。
  • using namespace std;这是一个语句,因此必定要用分号结尾。 这是C++中的命名空间,js中是没有的。
  • // main 其中// 表示单行注释,这里所在的语句表示程序开始的地方,咱们写代码通常都是要在这里写的。
  • 下一行 int main() 是主函数,程序从这里开始执行。
  • cout必定要和<<配合使用,指的是输出。
  • return 0; 表示终止函数,在C++中通常都是这样来写的。固然, return 8;  return 45;什么的都是能够的。
  • 注意:C++中和js同样,都是使用;分号来表示语句的结束,可是和js不一样的是,js某些状况下能够省略,可是C++中永远都不能够。

  注意:咱们也能够不适用 using namespace std; 可是在程序中咱们若是要使用cin和cout就必须在其前面添加 std::以下所示:

#include <iostream>

int main()
{
   static int zhu = 15;
   std::cout << zhu ;
}

 

  最终会输出 15

3.  C++中的标识符

  在C++中,可使用字母、下划线做为首字母,然后能够跟字母、下划线和数字。 注意:c++中是不支持$的,这点须要格外注意。 且C++是区分大小写的。

 

4.  和js同样,C++中也有一些保留字,咱们再给变量命名的时候,是不能使用的。

 

5. C++中的数据类型有哪些?

  • bool 布尔型
  • char 字符型
  • int 整型
  • float 浮点型
  • double 双浮点型
  • void 无类型
  • wchar_t 宽字符型

    上面是七种基本类型,一种基本类型还可使用一个多多个类型修饰符进行修饰。类型修饰符以下:

  • short 
  • long
  • signed
  • unsigned

  不一样的类型所占的内存是不一样的,咱们可使用sizeof()方法来输出,以下所示:

#include <iostream>
using namespace std;

int main()
{    
    cout << sizeof(int) << endl << sizeof(char) << endl << sizeof(bool) << endl << sizeof(double);
    return 0;
}

  如上面的代码会获得 4 1 1 8,能够看出double所占的字节数是最多的。

 

 

http://www.cnblogs.com/BeyondAnyTime/archive/2012/08/23/2652696.html  C++中的四种类型转化方式。

 

6. typedef 

 C++中typedef 的做用是将一个已有的类型的名称修改,def即定义的意思,以下所示:

typedef int zhu;
zhu vari;

 

  那么这时的vari就是整型变量。 

 

7. 变量的声明和初始化

int a;

bool b;

char c;

   上述都是变量的声明。咱们还能够在声明的同时初始化。

int a = 15;

bool b = true;

char c = "good";

int e = 15, f = 45;

  咱们还能够看到,咱们能够一次声明而且初始化多个变量。

  注意: 变量的初始化是一个好习惯,咱们最好每次再定义变量的时候都要初始化;

  看下面的例子:

#include <iostream>
using namespace std;


  
int main ()
{

 int zhu = 20;
 
  cout << zhu << endl ;

 
  return 0;
}

  最终会输出20。

  咱们再看一个函数调用的例子。

#include <iostream>
using namespace std;
int add();
int main ()
{
     add();
    return 0;
}
int add()
{
    int zhu = 10;
    cout << zhu;
}

  最终会输出20.

  注意:

  • 函数如何要调用,就必定要先声明,如 int add(); 或者之间在前面定义好。 
  • 另外能够看到C++中定义函数直接使用 int 变量名(); 即比通常的变量多了一个()便可。  且因为C++是自上而下执行的,因此咱们必须提早声明,这样,会自动找处处于下方的函数定义。

 

8. c++中的变量

  通常,在c++中能够有三个地方声明变量,一个是 代码块内部声明变量,此即局部变量。 还能够在函数的参数中声明变量,这是形式参数。 也能够在函数外面声明变量,这是全局变量

  其中局部变量只能在代码块中使用,全局变量能够在函数内也能够在函数外,即全局变量一旦声明,在整个程序中都是可用的。且和js同样,能够在代码块中声明和全局变量相同的名字,只是在代码块中使用会覆盖全局变量。

  以下:

#include <iostream>
using namespace std;
 
// 全局变量声明
int g = 20;
 
int main ()
{
  // 局部变量声明
  int g = 10;
 
  cout << g;
 
  return 0;
}

  最后输出的是 10。

 

9. 定义常量

  在C++中,定义常量有两种方式,一种是使用 #define 常量名 常量值  显然使用这种方式常量值的类型是不肯定的。 还有一种能够肯定常量值的类型的,就是使用 const 类型 变量名 = 变量值;   举例以下:

#include <iostream>
using namespace std;
#define zhu 100
int main() {
    const int he = 99;
    cout << zhu << endl << he;


}

  此代码最终就会输出 100 99。

 

10. C++存储类

  C++中的存储类用于定义其变量(函数)的声明周期和范围(可见性)。下面主要介绍几种:

  • 自 C++ 11 以来,auto 关键字用于两种状况:声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符。 这种方式彷佛和js中的var是同样的,咱们看看下面的例子:
#include <iostream>
using namespace std;

int main()
{
   auto zhu = 15;
    auto z = 'h';
   cout << zhu << endl << z;
}

  最终输出 15(int类型)和 h(字符)

  • register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(一般是一个词),且不能对它应用一元的 '&' 运算符(由于它没有内存位置)。使用register要声明类型,以下:
#include <iostream>
using namespace std;

int main()
{
   register int zhu = 15;
   cout << zhu ;
}
  • static咱们知道通常状况下全局变量会始终存在,可是局部变量一旦被调用事后就会被销毁。可是若是咱们使用 static 关键字。那么这个变量即便是局部变量也能够恒久存在,也就是说 static既能够用在局部变量也能够用在全局变量上。
#include <iostream>
using namespace std;

int main()
{
   static int zhu = 15;
   cout << zhu ;
}

  最终会输出 15

 

11. C++中的运算符

  在C++中,和其余语言同样,都有本身的运算符,如 + - / * 等等,指的注意的是,判断是否相等,使用 == 便可,不像js中使用 === 的状况。

  想要了解更多,点击这里

 

12. C++函数

  什么是函数? 函数就是不少语句组合在一块儿能够作某一件事情的东西。 这就是函数。每一个 C++ 程序都至少有一个函数,即主函数 main() ,全部简单的程序均可以定义其余额外的函数。

  另外:C++标准库还提供了大量的咱们能够直接使用的内置函数, 如 strcat()用于拼接两个字符串等等。

  和js的函数不一样的是,C++的函数直接使用 int 便可,固然最后在函数内部你也要返回相应的int值,如return 0;  另外就是在传递参数的时候要使用 int相似的类型肯定其类型,举例以下:

int max(int num1, int num2) 
{
   // 局部变量声明
   int result;
 
   if (num1 > num2)
      result = num1;
   else
      result = num2;
 
   return result; 
}

  这就是一个很常见的函数了, int肯定函数的类型, max为函数名,咱们调用函数的时候就使用该函数名。  传入两个参数,必须使用 类型声明。  最后返回一个int类型的值。

  固然这个是函数定义,咱们也能够在前面先声明,即 int max(int, int);  能够发现这里省略了 num1和num2,由于这些都是不重要的, 类型正确便可。

 

 

13. 函数参数

  c++中的函数参数是形式参数,其和函数内的其余局部变量其实是同样的。即在进入时被建立,  执行结束被销毁。

  以下所示:

     

  即通常状况下咱们使用的是传值调用,即这是把实际值复制给了函数的形式参数,因此,在这种状况下,修改函数内部的形式参数对实际值没有影响。  

#include <iostream>
using namespace std;

int a = 15;
int b = 20;
int modify(int, int);
int main() 
{
    modify(a, b);
    cout << "主函数的a:" <<a << endl << "主函数的b:" << b;    
}
int modify(int a, int b) 
{
    a = a + 85;
    b = b + 20;
    cout << "函数内部的a:" <<a << endl << "函数内部的b:" << b << endl ;
}

  结果以下:

函数内部的a:100
函数内部的b:40
主函数的a:15
主函数的b:20

 

     能够看到: 在函数内部修改了传进来的参数,只是修改了clone版本,并无修改真正的a和b。 这也就是传值调用。

 

在C++的函数中,咱们也可使用 参数的默认值,即若是传入了该参数,那么就是用; 若是没有传入,就是用默认值,以下所示:

int sum(int a, int b=20)
{
  int result;

  result = a + b;
  
  return (result);
}

 

14. C++中的数字运算

  咱们能够引入 cmath库,而后使用C++自带的数字运算的函数,举例以下: 

#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int a = -10;
double b = 4.54;
float c = 45.2;
cout << abs(a) << endl << sqrt(b) <<endl << pow(c, 2);

}

 

  注意:这里必须引用 cmath库,即 #include <cmath> 而后就可使用诸如 sqrt() abs() pow() floor() sin() cos() tan()之类的函数了。

 

15.  数组

  在C++中声明数组的方法很简单,即:

  int   numbers[10];

  其中int也能够换成其余你须要的类型,如 double等 。 在变量名后面的数字必定要大于0,这里为10表示这个数组中能够放下长度为10的数。

   咱们还能够初始化数组,只是这里初始化数组使用的是{},在数组的定义和初始化方面C++和js的差异较大。以下所示:

  

#include <iostream>
using namespace std;
int main()
{
int numbers[8] = {45, 12, 85, 56};
cout << numbers[0] << endl<< numbers[1] << endl<< numbers[2] << endl<< numbers[3] << endl;

}

  最终的输出结果: 45, 12, 85, 56

  咱们也能够不限制数组的长度: 如 int numbers[] = {45, 12, 85, 56};

 

16. C++字符串

  在C++中,因为字符串的特殊性,通常状况下,咱们是须要单独来将字符串的。在C++中有两种方式表示,一种是引入的C语言风格的,另外一种是C++特有的。

 char str[] = {'h', 'e', 'l', 'l','o', '\0'};

  字符串其实是使用 null 字符 '\0' 终止的一维字符数组。所以,一个以 null 结尾的字符串,包含了组成字符串的字符。 能够看出,这里字符串的写法与数组很是类似。

  还能够写成下面这种形式:

  char str[] = "hello";

     上面两种方式的字符串的效果是同样的。

     

  最终的存储形式就是这样,最后一位是使用null占位表示结束。

  在C++中,有大量的处理字符串的内置函数,若是但愿使用这样函数,须要引入cstring(正如数学运算引入了cmath同样)举例以下所示:

#include <iostream>
#include <cstring>
using namespace std;
int main() 
{
    char str1[] = "zhuzhenwei";
    char str2[] = "hetingting";
    cout << strlen(str1) << endl << strlen(str2) << endl;
    cout << strcat(str1, str2) << endl;
}

  最终输出:10 10  zhuzhenweihetingting

  上面所说的都是C语言中字符串的实现,下面的是C++的。

  C++ 标准库提供了 string 类类型,支持上述全部的操做,另外还增长了其余更多的功能。

  看下面的例子:

#include <iostream>
#include <string>

using namespace std;

int main ()
{
   string str1 = "Hello";
   string str2 = "World";
   string str3;
   int  len ;

   // 复制 str1 到 str3
   str3 = str1;
   cout << "str3 : " << str3 << endl;

   // 链接 str1 和 str2
   str3 = str1 + str2;
   cout << "str1 + str2 : " << str3 << endl;

   // 链接后,str3 的总长度
   len = str3.size();
   cout << "str3.size() :  " << len << endl;

   return 0;
}

  值得注意的是: 这里引入的是:#include <string> 而再也不是 #include <cstring>, 二者的区别在哪呢?  

  显然,cstring是c语言中的string,而string就是C++中类string,因此这里咱们用到了链式调用,能够看出面向对象的C++使用起来多么方便,若是js也能够这样随便引入,就太好了。

 

 

17. C++指针

  C++中比较有特点的固然就是指针了。这也是我复习C++的一个理由~  看完这个就要睡觉啦~  好困啊

  哈哈,让咱们先来看一看教程的说法:

学习 C++ 的指针既简单又有趣。经过指针,能够简化一些 C++ 编程任务的执行,还有一些任务,如动态内存分配,没有指针是没法执行的。因此,想要成为一名优秀的 C++ 程序员,学习指针是颇有必要的。

  恩,加油吧,捡起来这一部份内容,先看看下面的代码:

#include <iostream>

using namespace std;

int main ()
{
   int  var1;
   char var2[10];

   cout << "var1 变量的地址: ";
   cout << &var1 << endl;

   cout << "var2 变量的地址: ";
   cout << &var2 << endl;

   return 0;
}

  这和以前的有什么区别的?  恩,就是多了个&, 这在C++中是用来取地址的,即你这个变量住在哪?(变量的内存地址) 看看输出的结果:

var1 变量的地址: 0x7fff9d7403ec
var2 变量的地址: 0x7fff9d7403f0

  0X是指16进制的数字。

  那么什么是指针呢?

  指针是一个变量,其值为另外一个变量的地址,即,内存位置的直接地址。声明指针的方式以下:

type *name;

  如 int  *p;   这里就声明了一个p指针,注意:这里带有*, 是说我声明了一个指针,可是并非说*p是指针,由于p才是真正的指针,而*p是指这个p指针所指向地址的。  *和指针是密切相关的。以下面的声明方式都是有效的指针声明:

int    *ip;    /* 一个整型的指针 */
double *dp;    /* 一个 double 型的指针 */
float  *fp;    /* 一个浮点型的指针 */
char   *ch     /* 一个字符型的指针 */

  看看这个在C++中使用指针的例子:

#include <iostream>

using namespace std;

int main ()
{
   int  var = 20;   // 实际变量的声明
   int  *ip;        // 指针变量的声明

   ip = &var;       // 在指针变量中存储 var 的地址,由于指针的值是地址!!!!!!!!!! 而&var 就是在取变量var 的地址。

   cout << "Value of var variable: ";
   cout << var << endl;

   // 输出在指针变量中存储的地址
   cout << "Address stored in ip variable: ";
   cout << ip << endl;

   // 访问指针中地址的值
   cout << "Value of *ip variable: ";
   cout << *ip << endl; // 这里ip是指针,它的值就是地址,而*ip是地址所在的值,故最终是20

   return 0;
}

  结果以下:

Value of var variable: 20
Address stored in ip variable: 0x7fff99a46294
Value of *ip variable: 20

  

 

18.  C++引用

  引用变量是一个别名,也就是说,它是某个已存在变量的另外一个名字。一旦把引用初始化为某个变量,就可使用该引用名称或变量名称来指向变量。

   首先须要明白的是:引用不一样于指针。  

  

  通俗的讲(我的理解),引用就是一我的的小名。看,好比指明了我这个大名:

   int zzw = 8;

  即8是个人身体,而zzw是表明我这个身体的大名  。

  可是我还能够起一个小名,以下:

 int& pig = zzw; 

  也就是说不管是大名zzw仍是小名pig都指得是我本身, 叫我什么我都答应

  实例以下:

#include <iostream>

using namespace std;

int main ()
{
    int zzw = 8;
    int& pig = zzw;
    cout << zzw << endl << pig << endl;
    cout << "对引用进行修改" <<endl;
    pig = 20;
    cout << zzw << endl << pig;
   return 0;
}

  最终的结果以下所示:

8
8
对引用进行修改
20
20

  能够看到叫我小名我也答应你了(修改一个变量的引用,实际上就是修改它本身)。

 

19.  C++数据结构

  在C和C++的数组中能够定义存储相同数据类型的变量。 可是在C++中还提供了数据结构,在这个数据结构里咱们能够定义不一样类型的变量。

      

  具体应用举例以下:

#include <iostream>
#include <cstring>
 
using namespace std;
 
// 声明一个结构体类型 Books 
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
 
int main( )
{
   Books Book1;        // 定义结构体类型 Books 的变量 Book1
   Books Book2;        // 定义结构体类型 Books 的变量 Book2
 
   // Book1 详述
   strcpy( Book1.title, "C++ 教程");
   strcpy( Book1.author, "Runoob"); 
   strcpy( Book1.subject, "编程语言");
   Book1.book_id = 12345;
 
   // Book2 详述
   strcpy( Book2.title, "CSS 教程");
   strcpy( Book2.author, "Runoob");
   strcpy( Book2.subject, "前端技术");
   Book2.book_id = 12346;
 
   // 输出 Book1 信息
   cout << "第一本书标题 : " << Book1.title <<endl;
   cout << "第一本书做者 : " << Book1.author <<endl;
   cout << "第一本书类目 : " << Book1.subject <<endl;
   cout << "第一本书 ID : " << Book1.book_id <<endl;
 
   // 输出 Book2 信息
   cout << "第二本书标题 : " << Book2.title <<endl;
   cout << "第二本书做者 : " << Book2.author <<endl;
   cout << "第二本书类目 : " << Book2.subject <<endl;
   cout << "第二本书 ID : " << Book2.book_id <<endl;
 
   return 0;
}

  另外,数据结构也能够做为参数传递进去,以下所示:

#include <iostream>
#include <cstring>
 
using namespace std;
void printBook( struct Books book );
 
// 声明一个结构体类型 Books 
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
 
int main( )
{
   Books Book1;        // 定义结构体类型 Books 的变量 Book1
   Books Book2;        // 定义结构体类型 Books 的变量 Book2
 
    // Book1 详述
   strcpy( Book1.title, "C++ 教程");
   strcpy( Book1.author, "Runoob"); 
   strcpy( Book1.subject, "编程语言");
   Book1.book_id = 12345;
 
   // Book2 详述
   strcpy( Book2.title, "CSS 教程");
   strcpy( Book2.author, "Runoob");
   strcpy( Book2.subject, "前端技术");
   Book2.book_id = 12346;
 
   // 输出 Book1 信息
   printBook( Book1 );
 
   // 输出 Book2 信息
   printBook( Book2 );
 
   return 0;
}
void printBook( struct Books book )
{
   cout << "书标题 : " << book.title <<endl;
   cout << "书做者 : " << book.author <<endl;
   cout << "书类目 : " << book.subject <<endl;
   cout << "书 ID : " << book.book_id <<endl;
}

 

 

 

20. C++中的函数重载

   文章C++的函数重载无疑是很是棒的,这里仅仅摘录一部分作一个简单的了解,往后一定深刻。

   

1. 什么是函数重载?

  函数重载是指在同一做用域内,能够有一组具备相同函数名不一样参数列表的函数这组函数被称为重载函数。重载函数一般用来命名一组功能类似的函数,这样作减小了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处

  下面就是函数重在的例子,即实现一个打印函数:

#include<iostream>
using namespace std;

void print(int i)
{
        cout<<"print a integer :"<<i<<endl;
}

void print(string str)
{
        cout<<"print a string :"<<str<<endl;
}

int main()
{
        print(12);
        print("hello world!");
        return 0;
}

 

  最终的输出以下:

print a integer :12
print a string :hello world!

  即咱们调用函数名相同的函数(实现的功能也大抵类似)返回的值确实不一样的

  

 

 

2.为 什么要函数重载?

  • 试想若是没有函数重载机制,如在C中,你必需要这样去作:为这个print函数取不一样的名字,如print_int、print_string。这里还只是两个的状况,若是是不少个的话,就须要为实现同一个功能的函数取不少个名字,如加入打印long型、char*、各类类型的数组等等。这样作很不友好!
  • 类的构造函数跟类名相同,也就是说:构造函数都同名。若是没有函数重载机制,要想实例化不一样的对象,那是至关的麻烦!
  • 操做符重载,本质上就是函数重载,它大大丰富了已有操做符的含义,方便使用,如+可用于链接字符串等。

 

 

 

补充:

http://www.cnblogs.com/lzjsky/archive/2011/01/24/1943199.html

静态数据成员介绍

 

 

结束,有时间了再继续...

 

2017年3月31日更新(C++进阶)

  今天刚刚使用MinGW 和 nodepad++ 来编译和执行文件了,和visual C++ 6.0是同样的能够cin也能够cout,仍是很是激动的,趁此就多复习一些知识吧。

1. 下面这是一个含有类和对象的最简单的例子:

#include <iostream>
using namespace std;
class Person    // L类的定义
{public:
    void SetInfo()
    {
        cout<<"Input info to name,sex,age"<<endl;
        cin>>name>>sex>>age;
    }
    void Show()
    {
        cout<<"name:"<<name;
        cout<<"sex:"<<sex;
        cout<<"age:"<<age<<endl;
    }
private:
    char name[20];
    char sex[2];
    int age;
};       // 类声明结束,必需要有分号

int main() 
{
    Person person1,person2;
    person1.SetInfo();
    person2.SetInfo();
    person1.Show();
    person2.Show();
    return 0;
}

 其中class Person用来定义一个名为Person的类,能够把类看作一个模子,而后咱们用这个模子就能够创造形形色色的对象来了。值得注意的是,在class定义了以后,须要使用分号做为结束。

 另外,使用public是说其中的内容是公有的,能够被调用的,而privite是私有的,只能在内部被调用。这就体现了著名的封装性的特色。

 就是面向对象,它引入了类和对象的概念,类是用户自定义的数据类型,对象是该数据类型的变量。

 

2. 注意使用#define 定义常变量时,只是将变量进行了简单的替换,以下所示:

int x=1; int y=2;  #define R x+y    #define PI 3.1415926    cout<<PI*R*R;   最后实际输出的是  PI*1+2*1+2 而不是PI*(1+2)*(1+2)

而若是咱们使用const float PI = 3.14;也是相似的做用,也能够写成  float const PI = 3.14;  二者是等效的。

 

 

 

三、空指针和野指针

  int *p = 0; 或者是  int *p = NULL;  那么这里的p就是空指针。

  而int *q; 仅仅声明了这个指针q,可是不知道它指向了哪里,因此说是野的,即野指针。

  二者是不一样的,引入空指针的目的是为了防止使用指针出错,若是出现了空指针就会报错,状况:动态分配内存malloc()函数或new运算符的成功使用不会返回空指针,可是失败了就会返回空指针。

  若是定义了一个野指针,咱们就不知道它到底会指向何处,为了不不知指针指向了何处,在C++中通常习惯是定义了指针变量后当即初始化为空指针,而后在使用指针以前再给指针变量赋值,使指针有了具体指向以后再使用指针。

 

4. 指针与const

  • const int *p;(int const *p; 和前者是同样的)  这个的意思p是常量,即咱们不能经过 *p 来修改p所指向的值,可是能够直接修改p所指向的值, 也能够修改p的指向。 
    #include <iostream>
    using namespace std;
    int main() 
    {
        const int *p = NULL;
        int a = 20;
        int b = 30;
        p = &a;
        p = &b;
        *p = 50; // error: assignment of read-only location "*p"
        cout<<*p;
    }
        

     咱们能够修改b的值,这样*p会改变,也能够修改p的指向,可是若是经过*p来修改指向的值就报错,提示*p是只读的。

  • int *const p; 这里是指p指针是const的,一旦定义了,就不能修改p的指向。
    #include <iostream>
    using namespace std;
    int main() 
    {
        int *const p = NULL;
        int a = 20;
        int b = 30;
        p = &a; // 报错
        cout<<*p;
    }
        

     这里我已经定义p为空指针了,那么后面p又指向a就会报错。

  • const int *const p; 这里就是上述的综合,即不能修改p的指向也不能经过*p来修改p所指向的值。

 

 

5. void和void指针

  先说void , 函数 int func(void){return 0;} 和int func(){return 0;}在C++中都表示不接受任何参数,若是使用func(2)就会报错。可是在c语言中,若是咱们使用func(2)就不会报错,因此,为了更加严谨,最好使用void表示不接受参数。  另外咱们不能使用void a;这种形式来声明变量,由于void表示无类型的,若是你声明了这个变量,那么分配多少内存呢? 对吧。

  可是void是能够声明一个指针的。 答案是能够的。使用void声明一个指针,咱们就称为“无类型指针”,或者就称为void指针。 咱们知道,一个类型的指针必须指向相同类型的变量,可是void指针就厉害了,它能够指向任意类型的变量。可是void类型的指针在读取值和指针的赋值过程当中须要进行强制类型转换,缘由以下:

 不难想象,不管是什么类型的指针,它指向一个变量的首地址老是同样的,因此咱们才可使用void指针,但问题是: 若是咱们但愿经过这个指针来访问他所指向的变量,就得知道这个变量的类型啊,由于不一样类型的变量的内存大小是不同的,因此得强制类型转化,告诉它这个变量的大小是多少,才能够读取。

#include <iostream>
using namespace std;
int main() 
{
    void *p;
    int a = 5;
    double b = 10;
    p = &a;
    cout<< *(int *)p;
}

  如上,必须进行强制类型转换才能正确的输出p所指向的变量,注意:强制类型转换是(int *)由于这是一个指针。 

 

 

6. 使用new和delete动态管理内存单元

  和声明一个变量不一样,使用new通常是用来申请指针的内存单元的,而且前者是在编译过程当中分配的内存,然后者是在程序的执行过程当中才分配的内存,因此是动态分配内存。 另外,new以后必定要delete,由于声明的方式能够自动地清除内存,可是new的方式只能使用delete来清除内存。

#include <iostream>
using namespace std;
int main() 
{
    int *p = NULL;
    p = new int;
    delete p;     
    cout<<*p;
}    

 

 最终输出的是16323288, 注意这是new到的一个内存,因此这是一个随机数。  且new和delete必需要成对存在。咱们还能够在new的时候初始化,即p = new int(20); 那么*p就是20了。

那咱们怎么申请连续空间的内存呢? 方法也很简单,就是p = new int[20]; 这样就能够申请到长度为20的连续空间了。

 

 

7. 引用,如 int &a = b;这就是a对b的引用,能够看作a是b的另一个名字,可是他们指向的同一个内存单元,因此对他们任意一个的修改都是有效的。 下面咱们看三个典型的例子,分别是值传递、指针传递和引用传递。

#include <iostream>
using namespace std;
int fun(int a, int b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}
int main() 
{
    int x = 5, y = 10;
    cout<<" x:"<<x<<" y:"<<y<<endl;
    fun(x,y);
    cout<<" x:"<<x<<" y:"<<y<<endl;
}
    

  最后的结果都是x为5,y为10。这就是典型的值传递,即穿进去以后,内部的改变不会影响外面的。

  

#include <iostream>
using namespace std;
int fun(int *a, int *b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}
int main() 
{
    int x = 5, y = 10;
    cout<<" x:"<<x<<" y:"<<y<<endl;
    fun(&x,&y);
    cout<<" x:"<<x<<" y:"<<y<<endl;
}
    

  最后的结果是: x:5,y:10  后面是x:10,y:5  能够发现这个交换就完成了。  这就是典型的指针传递或地址传递。这样,在内部修改的*a和*b实际上就在修改x和y。

 

 

#include <iostream>
using namespace std;
int fun(int &a, int &b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}
int main() 
{
    int x = 5, y = 10;
    cout<<" x:"<<x<<" y:"<<y<<endl;
    fun(x,y);
    cout<<" x:"<<x<<" y:"<<y<<endl;
}
    

 

  最后的结果是: x:5,y:10  后面是x:10,y:5  能够发现这个交换就完成了。  这就是典型的引用传递,二者都是指向一样的内存,因此能够完成修改。

 

值得注意的是,在引用中,仍是有const的,如const int &a = b;表示a这个引用是不能被修改的,即不能经过a来修改他和b共有的内存,即a的权利只是读。以下:

#include <iostream>
using namespace std;
int main() 
{
    int x=10;
    const int &b = a;
    b = 20;
    cout<<a;
}   

 

 编译过程当中就会提示b是只读的。

 

 

 8. 函数的相关问题

  在c++中,不管你写了多少,老是从main函数中开始执行,而且在调用一个函数以前,咱们必须进行函数声明(函数声明和函数定义不一样,因此说须要用分号做为结尾),另外,main函数是最重要的,咱们强烈建议将函数定义写在main函数以后,另外, 在函数声明的时候咱们只须要将函数的类型声明便可, 名称不重要,编译时不会检查。

  除此以外,咱们还能够提供默认的参数,即若是没有传递该参数,咱们就使用默认的。且默认的参数可使其中的一个或几个(固然可使所有),可是若是不是所有时, 默认的参数需从最右边开始。

#include <iostream>
using namespace std;
int main() 
{
    int add(int,int,int =50);
    //int add(int,int,int c=50); // 这个也是有效的,在函数什么声明的过程当中,不须要制定名字。
    cout<<add(5,10,15)<<endl; // 30
    cout<<add(5,10);
}
int add(int a,int b,int c = 50)
{
    return a + b + c;
}
    

  值得注意的是,若是使用默认参数,那么定义和声明都须要指明默认的值,不然就会报错。 虽然咱们能够直接写在int main()的上面,这样就不须要声明了,可是这并非咱们所推荐的。

 

   函数重载: 即函数参数的类型不一样或个数不一样或函数参数的类型和个数都不相同。函数的返回值能够相同也能够不一样,可是毫不能函数的参数形同而只有返回值不一样,这不是函数的重载。以下:

#include <iostream>
using namespace std;

int main() 
{
    int add(int,int);
    int add(int,int,int);
    int a = 5,b = 8;
    int x = 14,y = 15, z =45;
    cout<<add(a,b)<<endl<<add(x,y,z);
}
int add(int a, int b, int c)
{
    return a+b+c;
}
int add(int a, int b)
{
    return a+b;
}

  一个输出的是13,另外一个输出的是74。

 

9. 详解名字空间

  我以前所写的全部代码中都包括: using namespace std; 不难理解,这必定和命名空间是由关系的。下面我将从头提及。。。

 (1)为何要使用名字空间?

   简单的说,使用名字空间是为了解决程序中名字冲突的问题,即在程序运行过程当中遇到相同名字的变量,系统不能正确的区分它们。

  在一个小型系统里,只要咱们注意一下变量就不会重复,可是对于一个大型的系统,由多人合做完成,咱们经过#include的方式来引入不一样的开发人员所编写的程序,那就不免会遇到重名的状况,这样就致使类全局名字空间污染。

  正是为了不这样的问题,后来引入了名字空间的机制。(在早期的C++中,也是没有名字空间的概念的)。

 (2)什么是名字空间?

  所谓名字空间就是一个由程序设计者命名的内存区域。他能够根据须要创建一些有名字的命名空间域,把一些全局标识符分别放在不一样的名字空间中,这样就能够解决变量冲突的问题了。 就向一个文件下有一个目录,每一个子目录又有一堆文件,那么各个目录下的文件是能够重名的,因而就解决了问题。

 (3)如何使用名字空间?

  语法以下: 

namespace 名字空间名
{
    定义成员  
}

 

   其中成员的类型包括:常量、变量、函数、结构体、类、模板等,还能够是名字空间,即名字空间的嵌套。以下:

namespace ns
{
   const int RATE = 0.08;
   double money;
   double tax()
  {
    return money * RATE;
  }  
  namespace ns2
  {
      int count;
  }
}

 

若是要访问名字空间ns中的成员,就能够采用“名字空间::成员名”的方法,如ns::RATE、ns::money、ns::tax()、ns2::count等等。

咱们还能够给ns起一个别名,即namespace anotherns = ns; 那么就是anotherns::money就和 ns::money的效果是同样的了。

  技巧: 使用using 名字空间的成员名,如using ns::tax 后面再访问tax()的时候就至关于ns::tax(),这样能够避免在每一次访问名字空间的成员时用名字空间限定,来简化名字空间的使用。

  技巧: 使用using 名字空间名, 若是在一段程序中常常访问一个名字空间中的多个成员,就要屡次使用using名字空间成员名,这是很不方便的,因此C++提供了using namespace 语句,一次就能声明一个名字空间中的所有成员,格式为:

  using namespace 名字空间名;

  注意1: 该声明下使用变量只在该声明的做用域内有效。

  注意2: 若是同时使用using namespace引入了多个命名空间,那么要保证它们没有相同的变量名,不然仍是会有命名冲突。

  

  (4)标准名字空间 std

  即standard,标准的名字空间,系统预约义的头文件中的函数、类、对象和类模板都是在std中定义的。

  因此,第二行都有一个using namespace std; 这就在全局中起做用了,若是不用的话,咱们就要使用std::来访问了,以下所示:

#include <iostream>
int main() 
{    
    std::cout << "Hello world";
}

 

  若是引入了大量的系统的函数、类等,咱们就须要添加没玩没了的std::,而后这是很不方便的。

 

  

9. 字符串变量

  咱们知道在c中使用char来定义字符串和字符串数组都是十分麻烦的。而在c++中,因为有了类的概念,而且系统自带的就有string类,咱们只要在开头引入便可,即#include <string>而后咱们就可使用string类了。

  如 string str = "hello"; 这样就定义了一个字符串变量,咱们能够对这个变量进行大量的操做,如strcat、strcopy等等。另外,还能够赋值,而且不须要考虑内存的问题。

  和c中的最大的不一样是,在c中的字符串,最后自动添加'\0'做为结尾,而string实例化的对象不须要使用'\0'做为结尾。且可使用str[0]等来访问到每个字符。

  在c++中,还支持数组,如 string str = {"hello", "world", "hhahha"}; 即咱们不须要考虑每个元素的长度是否一致等。 就是这个方便。