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"}; 即咱們不須要考慮每個元素的長度是否一致等。 就是這個方便。   

     

相關文章
相關標籤/搜索