C++學習筆記

> (1)定義常量
   const  datatype CONSTANTNAME=value;
例如定義一個int常量,其值是1const int CONSTNUMBER=1;[一般常量我們喜歡用大寫字母表示]
(2)指數運算符。
pow(a,b)用來計算a的b次方是多少!
pow是在cmath庫文件中定義的函數。
(3)數值類型的轉換
通過使用轉換運算符static_cast<type>(value);
注意:類型轉換並不改變被轉換變量的值。
例如:double d=5.5;
int i=static_cast(5.5);
轉換完之後的i=5,d依舊是5.5;
(4)string字符串的輸入
c++在string頭文件中提供了getline函數,默認情況下,輸入是以空白字符結束,如果你想輸入Happy New Year就必須使用getline函數。
具體使用示例:
string city;
cout<<"enter your city name"<<endl;
getline(cin,city,'\n');//這表示以'\n’來表示輸入,由於第三個參數默認值是'\n’,所以可以省略,變成getline(cin,city);
(5)函數原型。
如果main函數在前,而main函數要使用的函數在main函數之後才定義,需要在程序中聲明要使用的函數的原型。
#include<iostream>
using namspace std;
int test(int i);//這就是函數原型
int main(){
......
test(5);
return 0;
}
int test(int i){
rerurn i;
}
(6)缺省參數
缺省參數就相當於默認參數。
例如:void test(int i=5){
......
}
如果調用這個函數時沒有傳入參數I是多少,則默認是5。

(7)數組的聲明和初始化。
例如:int mylist[2]={2,3};
不能這樣子。
int mylist[2];
mylist={2,3}
因爲數組的初始化語句只能在一條語句中完成。

(8)數組作爲函數參數。
例子:
void test(int list[]){
............
}
使用方式:
int a[]={2,3,4,5,6};
test(a);
如果在函數參數裏面的int list[]前面加上了const
就不能在函數裏面修改傳入的數組。
例如:
void test(const int list[]){
list[0]=100;//出錯,不能修改出入進來的數組的值
}
(9)數組不可以作爲函數返回值返回。
例如:int []  test(const int list[]){
......
}
c++中是不允許的。
如果實現類似返回數組的功能可以使用兩個數組。
例如:
void test(const int list[],int newlist){
for(int i=0;i<list.size();i++){
list[i]=newlist[i]
}
}

(10)字符串相關函數
strlrn(char s[]);   返回字符串的長度,即在空終結符之前的字符個數。
strcpy(char s1[],const chars2[]);  將字符串s2複製到s1中去。
strncpy(char s1[],char s2[],size_t n); 將字符串s2前n個符號複製到S1中。
strcat(char s1[],const char s2[]);把字符串s2拼接到s1之後。
strncat(cgar s1[],char s2[],size_t n); 將字符串s2前n個符號拼接到S1之後。


(11)類定義和類實現的分離。
類定義:
定義在Circle.h文件之中
class Circle{
publicdouble radius;
Circle();
Circle(double r);
double getRadius();
}
類實現:
實現在Circle.cpp文件之中
注意在類文件實現的文件Circle.cpp文件的頭部要包含以下的文件。
#include "Circle.h";
Circle::Circle(){
    radius=1;
}
.............

(12)使用typedef來定義同類型。
例如:typedef int integer;
  這樣可以使用integer來聲明int變量。
例如:integer a=10;  
相當於   int a=10;

(13) c++中函數的參數有按值傳遞和引用傳遞兩種
   void test(int n1,int n2){
     }//按值傳遞。
   void test(int &n1,int $n2){
    }//引用傳遞。
有什麼區別呢?
按值傳遞的方式有很大的侷限性。
例如函數swap( ):
void swap(int n1,int n2){
       cout<<"inside swap and before invoking n1 is''<<n1<<"n2 is"<<n2<<endl;
int temp=n1;
n1=n2;
n2=temp;
cout<<"inside swap,after invoking n1 is"<<n1<<"n2 is"<<n2<<endl;
}//這是按值傳遞參數,那麼來看一下按值傳遞的方式的侷限性在哪裏。
在main函數中調用這個函數。
int main(){
  int num1=1;
  int num2=2;
  cout<<"before nvoking num1 is"<<num1<<"num2 is"<<num2<<endl; 
   swap(num1.num2);
   cout<<"after invoking num1 is"<<num1<<"num2 is"<<num2<<endl; 
}
輸出結果是:
(1)before nvoking num1 is 1 num2 is 2;
(2)inside swap and before invoking n1 is 1 n2 is 2;
(3)inside swap after invoking n1 is 2 n2 is 1;
(4)after nvoking num1 is 1 num2 is 2;
可以看到只是函數內部的n1和N2被交換了值,而num1和num2在調用之前和調用之後的值依舊不變。這是因爲實際上num1和num2的值被傳遞給了n1和n2。
當n1和n2有了值以後在內存中的地址與num1和num2的地址是不一樣的,所以改變n1,n2的值
與num1和num2無關。【按值傳遞的侷限性就體現在了這裏】
既是把swap函數變成了
swap(int num1,int num2){
.......
}//把傳入的參數的名字變成num1,num2.也還是一樣的結果,這與參數名字無關。

所以可以採用引用傳遞來實現交換之後num1和num2的值也變了。
瞭解引用傳遞之前,先來了解一下引用變量。
引用變量是一種特殊的變量,可以通過引用變量來訪問和修改存儲在變量中的原數據。
聲明一個引用變量,可以在變量名前或者是數據類型之後加上一個'&'符號。
例如:int   &r;
           int&   r;【一般採用這一種】
把swap函數變成swap(int& n1,int& n2){
......
}
這樣調用swap函數之後的num1和num2就會交換數據了。


(14)指針學習
理解指針第一步:
     聲明指針只需要在聲明指向的數據類型之後加上*。
     例如  int  a;【聲明一個int類型的變量a】
     int *   a;【聲明瞭一個指向int類型數據的內存地址的指針a】     
     指針變量保存的是內存地址,運算符*可以訪問指針指向的內存地址的數據。 
     &是地址運算符。
     假設定義了一個指針 int *   count,則&count是count的地址。
     可以使用&將一個指針的地址賦給另一個指針。
     例如:    pcount=&count;
     指針可以在聲明是賦值,也可以在聲明之後賦值。
第二步:
    常量指針。
    常量指針指向的是一個不變的內存位置,但是該內存位置處的實際值是可以更改的。
    聲明一個常量指針
    int const *  p;p就是一個常量指針。
    可以修改p指向的內存地址的值,例如*p=10;
    也可以使得一個常量指針指向內存位置處的實際值不可以改變,變成了const int const * p=10;
   第一個const是常量數據,第二個const是常量指針。
第三步:
   函數調用的時候傳遞指針參數。
   繼續來講swap函數,下面定義兩個swap函數,分別爲swap1(),swap2()。
  swap1(int*  p1,int* p2){
   int temp=*p1;
    *p1=*p2;
    *p2=temp;
   }//相當於按值傳遞
  swap2(int*  &p1,int*  &p2){
   int* temp=p1;
   p1=p2;
   p2=temp;
  }//相當於引用傳遞,唯一需要注意的是int *  &p1之後是地址的傳遞,不是值的傳遞了!!!
再說一前面說數組傳參數的問題。
void test(int list[])可以被替換爲void test(int* list,int size);
也就是說函數中的數組參數都可以用指針參數來替換。
第四步:
從函數中返回指針。
例如:
int* reverse(int* list,int size){
for(int i=0,j=size-1;i<j;i++,j--){
int temp=lits[j];
list[j]=list[i];
list[i]=temp;
}
return list;
}
相對應的原型可以寫成。int* reverse(int* list,int size);
第五步:
對象指針。
定義一個類Cricle,其內有成員函數
getName(){
return this.name;
}
定義一個對象指針。
Cricle* p;
指針訪問的成員函數和成員變量使用符號’->'。
例如:
p->getName();
第六步:
this指針指向被調用的對象本身。

(15)內存分配問題。
c++支持動態內存分配,這使得我們能動態的分配持久的內存空間,動態內存的分配使用new操作符。如下:int*  p=new int(4);
釋放內存使用delete。
如下:   delete p;
注意,如果有一個內存是爲了一個數組所分配的,爲了正確的釋放內存,則需在關鍵字delete和指針間加上符號[].如下:
delete [] p;
還需要注意的一點事delete只能用於那些指向new操作符創建的內存的指針。
例如一下采用delete來刪除一個不是由new創建的內存空間就會導致錯誤。
int x=10;
int * p=&x;
delete p;//出錯。

(16)析構函數。
析構函數是在對象被銷燬的時候調用的,創建一個析構函數只需要在方法前面加上符號‘~’。

(17)struct學習總結。
數組中的數據的類型必須是一樣的,但是struct中的的數據類型可以是任意的。
定義一個struct。方式如下:
struct Address{
  string name;
  string number;
.........
};
//與類的定義基本一致,class Address{  .......}
struct的使用方式和class也基本相似。
如下使用struct Address。
void f( ){
Address jd;
id.name='xza';
}
但是例如以上的使用方式並不是常用的。
最常用的方式是使用結構指針,如下:
void pritnAddress(Address* p){
   cout<<p->name<<endl;
}
另外需要注意的是:
(1)結構體變量可以在定義的時候指定初始值。例如:
Address q={beijing,3457890}
另外結構體也可以變成結構體數組,例如:
Address  a[3];它表示是定義了一個數組,數組存放的數據類型是Address,數組名字是a,他的長度爲3。
(2)c++中struct和類的區別在於struct不能有方法,所有成員是public的。
(3)可以在聲明struct的時候聲明一個struct實例。方法如下:
struct Address{
  string name;
  string number;
} adr;

   (18)模板學習。
     例如下面的兩個函數就可以抽象成模板。
    int  max(int x,int y){
         return x>=y? x,y;   
     }
   double max(double x,double y){
            return x>=y? x,y; 
    }
因爲這兩個函數的功能是一樣的,只是傳入的參數的數據類型和返回的數據類型不一樣而已。
抽象成模板如下:
template<typename T>//注意這裏沒有用';'結尾。
T max(T x,T y){
   return x>=y? x,y;
}
其中template<typename T>是模板前綴,其中的T是類型參數。[類似於java中的泛型]
同時,可能一個模板函數有多個類型參數,則可以這樣寫,template<typename T1,typename T2,typename T3>
另外,需要注意的是模板函數是按值傳遞的。
按引用傳遞的話可以將模板函數參數設置成爲以下例子中所示的格式。
例子:template<typename T1>
          T  test(const T& value1,const T& value2){
            .......................      
            }
提升知識:模板類
模板類
例如:
template<typename T>
calss Address{
T name;
T getName();
}
//構造函數
template<typename T>
Address<T>::Adress(){

}
template<typename T>
T Address<T>::getName(){

}

需要注意的是模板類不能分開定義和實現。
同時每一個具體實現函數之前都需要加上template<typename T>,同時在實現的方法中要在類之後加上<T>,如上兩個函數一樣。
發佈了47 篇原創文章 · 獲贊 26 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章