c++基礎知識筆記一

honghu79 12年前發布 | 2K 次閱讀 google應用商城 AbiWord PMD


 C++
 
 C++基礎語言與C語言差不多是一樣,只是多了些內容,變了些內容
 C++類型檢查更嚴格,更加豐富
 面向對象
 
 C++變量里面不僅是數據,還有函數;
 封裝,基本目的:我的數據是安全的
 繼承和多態
 
 c++還增加了模版,通用類型編程;
 異常處理
 
 g++
 c++
 
 gcc
 cc
 
 vi xxx.cpp  cpp===>c plus plus或者.cc,.C,.cxx的擴展名
 c++頭文件以.h或者.hpp
 
 編譯g++
 只編譯g++ -c xxx.cpp==>xxx.o
 
 g++ xxx.o===>a.out;g++ xxx.o -onewname
 
 g++ xxx.cpp===>a.out;g++ xxx.cpp -onewname;
 //注釋
 
 
 在c++中輸入輸出更多的是用cin/cout,其頭文件是iostream
 
 namespace===>
 標準庫都放在std的一個名字空間里面;
 //using namespace std;//即可使用這個名字空間下的東西了。
 
 
 vi  hello.cpp
 #include <iostream>//input/output stream
 #include <string>
 //using namespace std;//意味著標準庫中的所有東西都可用,在本例中可以采用以下方式替代。
 using std::cout;//可以采用A::B來表示A范圍內的B,“::”稱為域操作符
 using std::cin;
 using std::string;
 using std::endl;
 
 int main()
 {
  //在c語言里面使用scanf/printf,用%d等來使用;根據不同類型用不同的類型標識符
  cout <<"請輸入您的姓名和年齡:\n";//不管什么類型的數據都可以
  //std::cout<<"請輸入您的姓名和年齡:\n";//也可以不引進namespace,直接采用這種方式直接來使用
  string name;//不需要指明多少個元素;使用的是動態內存,
  int age;
  cin >>name >>age;
  cout <<name << "您好,您出生于"<<2012-age <<"年”
   <<endl;//endline==>'\n';c++里面允許用endl來換行
  
  //return 0;//在c++中末尾的return 0是可以不寫的,但不代表沒有。
 }
 
 g++ hello.cpp
 a.out
 
 
 
 vi namespace.cpp
 #include <iostream>
 using namespace std;
 #include <string>
 namespace lhj{//自己定義命名空間
  string name="老虎機";
 }
 namespace sxl{
  char name[20]="hahahhaha";
 }
 using namespace lhj;
 using namespace sxl;
 char name[20]="wl";
 int main()
 {
  //count <<"i love" << name <<endl;//歧義:老虎機?hahahhahahah
  count <<"i am" << lhj::name <<endl;
  string name="chch";
  cout << name << "very beautiful" << endl;//內部的name:chch
  cout << ::name <<"very beautiful,too" <<endl;//全局的name:wl
  //在這里::表示全局的name或者外部的name
  return 0;
  //設計的時候,盡量避免重名
 }
 
 string字符串類型,實際上就是封裝的類型;封裝的是指針和一系列的函數
 
 對比string與char str[100](這兩個都可以保存數組)
 string s1;//最大保存1個G==>c++風格的字符串===>=號就可以賦值==》連接用+=就可以=》比較==,!=,>,<,<=,>=
 char===>大小s1.size()/s.length()==>s1.find(...)查找==》s1[i]訪問某個元素===》s1是一個變量 s2[100];//保存99個字符+1個'\0';==>c風格字符串===strcpy(s2,...)=》連接strcat(s2,...)==》strcmp(s2,...)比較==>strlen(s2)==>查找,strchr或者strstr(s2)==》訪問某個元素s1[i]===》s2是一組變量
 
 在c風格和c++風格轉換,c風格會自動轉換成c++風格;c++風格轉換成c風格,使用s1.c_str()
 
 
 
 enum
 在c里面當作整數,而在c++里面
 
 #include <iostream>
 using namespace std;
 #include <string>
 enum Course{UNIX,C,CPP,UC,VC};
 struct Student{
  string name;
  Course co;
 };//定義一個結構
 enum Color{BLACK,RED,GREEN,YELLOW,BLUE,WHITE};
 int main()
 {
  Course c;
  Student s;
  int n;
  c=CPP;
  n=CPP;//這樣是可以的
  //c=n;//這樣就會報錯,enum在C++當作是一個獨立的類型;enum提升成int類型是可以的
  Color clr=BLUE;
  //clr=VC;//Course--->Color必須強制轉換
 
 }
 在C++中調用函數時不做類型提升,函數形參是...的函數按照C語言提升
 
 bool  true-1/false-0
 
 #include <iostream>
 using namespace std;
 int main()
 {
  bool gender=true;
  bool sex=false;
  cout <<(gender?"帥哥":"美女")<<endl;
  cout <<(sex?"boy":"girl")<<endl; 
  cout << gender << ',' << sex << endl;//輸出1,0
  cout << boolalpha <<gender << ',' <<sex << endl;//輸出true,false
 }
 
 引用reference==》給個變量,另起個名字(別名) T&
 vi reference.cpp
 #include <iostream>
 using namespace std;
 int main(){
 
  double d=123.45;
  double & e=d;//引用必須初始化,只能用變量來初始化;e是d的別名,兩者是同一個變量
  //double * const E=&d;//后面的e都相當于*E
  //double & f=123.45;//是一個錯誤
  const double &c=234.56;//這是正確的常量引用
  const double &s=d+5;
  cout << "&d=" << &d << ",&e=" << &e << endl;
  //int & n=d;//類型不一致
  cout << "d=" << d << ",e=" << e << "c=" <<c << "s=" << s << endl;
  double & e2 = e;
  cout << "&e2=" << &e2 << ",e2=" << e2 <<endl;
  e2=78.9
  cout << "e2=" << e2 << "d=" << d << endl;
 }
 
 引用的本質就是指針
 
 
 vi const.c
 #include <stdio.h>
 
 int main()
 {
  const int n=100;//n是常量;后面使用n的值的地方會直接用100代替
  volatile const int m=200;//不管何時都從內存中去重取,不管是c還是c++
  int *p=(int*)&n;//通過n找到內存地址
  *P=123;//將*p的內容更改為123
  p=(int*)&m
  *P=456;
  printf("%d,%d\n",n,m);
  return 0;
 }//耍流氓嘍
 使用cc const.c
 執行后n為123

 g++  const.c時,顯示為n=100;//經常c++編譯器之后,編譯器會優化;常會再從內存中讀取。量
 
 
 g++ -S const.c//會產生匯編語言;
 
 c++里面提倡不要做強制類型轉換;
 
 C++提供了4個強制類型轉換的算子
 static_cast | const_cast | reinterpret_cast | dynamic_cast
 //static_cast數值類型之間,有一方是void*的指針類型之間
 //const_cast把常量轉換成變量,用于臨時去掉const限制
 //reinterpret_cast用于任意兩種指針類型之間,以及指針類型與數值類型之間轉換;==》最危險的一種轉換
 //dynamic_cast用于父子類之間
 //屬于什么原因來轉換;兩種不相關的類型轉換;_cast
 
 #include <iostream>
 using namespace std;
 #include <cstdlib>  //c語言頭文件在c++中有個對應的頭文件,即類似<stdlib.h>---><cstdlib>
 int main()
 {
   //int n=45.67;//x,可能換丟失精度
   int n=static_cast<int>(45.67);
   int *p=static_cast<int>(calloc(sizeof(int),10));//calloc(unsigned n,unsigned size)在內存的動態存儲區中分配n個長度為size的連續空間,函數
   //返回一個指向分配起始地址的指針;如果分配不成功,返回NULL。 //跟malloc的區別;calloc在動態分配完內存后,自動初始化該內存空間為0,而malloc不初始化,里面數據是隨機的垃圾數據
    const int k=n;
    cout << "k=" << k << endl;
    const cast<int&>(k)=789;
    cout << "k=" << k << endl; 
    float f=123.45;
    p=reinterpret_cast<int*>(&f);
    cout << *p << endl;
    n=int(12.34);
    cout << "n=" << n << endl;
    n=int();//表示數值0
    cout << "n=" << n << endl;
    int m(100);
    cout << "m=" << m << endl;
    //int x();//函數聲明
   
 }
 
 ~!|& 有些系統輸入不了,都可以用關鍵字來代替如以下
 
 ~代compl   ^代xor   !代not  |代bitor  ||代or   &代bitand  &&代and
    &=代and_eq   |=代or_eq  ^=代xor_eq !=代not_eq
 
 -----------------------------------------------------------
 
 new  delete C++中提供動態內存
 new 類型;new就是申請一塊內存
 vi new.cpp
 
 #include <iostream>
 using namespace std;
 #include <cstdlib>
 #include <string>
 #include <new>
 //new 類型===>(類型*)malloc(sizeof(類型))
 int main()
 {
  int *p=static_cast<int*>(malloc(sizeof(int)));
  int *q=new int;//與上面是等效的;//不保證是0
  int *r=new int(888);//申請一個空間,并設置其初始值為888
  int n=10;
  cout << "請輸入一個整數:";
  cin >> n;
  int *a=new(nothrow) int[n];//可以通過new申請一個數組的空間,并返回數組的開始地址(第一個元素的開始地址);
  //會處理類型的問題
  //不保證清0;
  cout << *q  << ',' << *r <<endl;
  for (int i=0;i<n;i++){//int i,在這個for循環內可用,出了就不能用了。
   cout << a[i] << ' ';
   if (a[i]){
    cout << flush;
    char c;
    cin >> c;
   }
  }
  cout << endl;
  delete r;r=NULL;
  delete q;q=NULL;
  delete []a;a=NULL;//告訴系統刪除的是一片空間,中間加[]
  //用new申請的,用delete釋放
  
  free(p);//malloc申請的內存,不要用delete p
 }
 
 
 成員指針
 
 
 vi memberptr.cpp
 #include <iostream>
 using namespace std;
 //結構變量.*成員指針,結構指針->*成員指針
 struct date{
  int year;
  int month;
  int day;
  void print(){cout << year << '-' << month << '-' << day << endl;}
 };
 void showmemeber(date a[],int n,int date::*p)
 {
  for(int i=0;i<n;i++){
   cout << a[i].*p <<' ';
   //cout << *(a+i).*p << ' ';
   //cout << (a+i)->*p << ' ';
  }
  cout << endl;
 }
 int main()
 {
  date a[5]={{2010,8,17},{2010,10,1},{},{},{}};
  date d{1997,7,7};
  cout << "&d=" << &d << endl;
  cout << "&d.year=" <<&d.year << ",&d.month=" << &d.month << "&d.day=" << &d.day << endl;
  //&date::year;//取相對地址
  cout << &date::year << &date::month <<&date::day << endl;
  cout << &main <<&f <<endl;
  
  union{
   int n;
   int date::*mp;//成員指針
   
  };//這兩個變量占用同一個內存空間;
  mp=&date::day;
  cout << "n=" << n << endl;
  cout << d.*mp <<endl; //.*當作一個運算符
  mp=&date::year;
  cout<<d.*mp<<endl;
  showmember(a,5,&date::month);
  showmember(a,5,&date::year);
  d.print();
 }
 
 
 
 
 #include <iostream>
 using namespace std;
 
 void f1(){cout << "hello" << endl;}
 void f2(void){return f1();}
 void f3(double){cout <<"world" <<endl;}//有類型無名字:啞元;一般是兼容性的考慮
 int main()
 {
  //f1(123);函數f1是無參的
  f1();
  f2();
  f3(12.3);
 }
 
 
 c++標準庫包含了c語言的標準庫,又進行了擴展以及標準模版庫STL
 
 引用必須有變量才行;常量引用必須加const
 常量必須有const
 函數地址只能用來調函數
 成員地址能用用來訪問成員
 函數地址和成員地址在輸出的時候,c++中都強制處理成true或1,不管是什么東西。怎么訪問呢?可以通過聯合union來訪問;而在c語言中,訪問的可能就是地址
 
 
 引用一般最多的是作為形參或者返回值、返回類型
 
 #include <iostream>
 using namespace std;
 
 int main()
 {
  int i;
  for (i=0;i<5;i++)
  {
   cout << i << endl;
  }
  cout << i << endl;
 }
 //在c語言中,for (int i=0;i<5;i++)  //這個i只在for循環范圍之內,而在vc中再可以在內外都可以
 
 引用作為函數的形參,可以減少數據傳輸的數量;比如結構變量,如果只是一個基本類型變量就無所謂了。
 
 #include <iostream>
 using namespace std;
 void JiaoHuan(int *a,int *b){int t=*a;*a=*b;*b=t;}
 void JiaoHuan(int& a,int& b){int t=a;a=b;b=t;}
 void print(cont int & n)//用16進制輸出
 {
  cout << hex << showbase << n << endl;//hex16進制,showbase顯示幾進制
 }//8進制0開頭,16進制0x,10進制什么都不帶
 
 struct Window{
  string text;
  int x,y;
  int width,height;
 };//GUI
 //Window input(){
 input(Window& r){ 
  //Window w;
  //...
  cout << "請輸入窗口標題、xy坐標、寬度高度:\n";
  cin >> r.text >> r.x >> r.y >> r.width >> r.height;
  
  return w;
 
 }
 void print(const Window& r)
 {
  cout << "========" << r.text << "=========" endl;
  cout <<"從(" << r.x << ',' << r.y <<")到(" << r.x + r.witdh << ',' << r.y + r.height <<")"\n;
 }
 int main()
 {
  int m=10;n=20;
  JiaoHuan(&m,&n);//通過地址來交換值
  cout << m << ',' << n << endl;
  JiaoHuan(m,n);////實參初始化形參,引用是用誰初始化就是誰的別名或引用
  cout << m << ',' << n << endl;
  void(*p)(int &,int &)=&JiaoHuan;//孤立的去看函數的地址是沒有意義的,必須看其賦值給誰
  p(m,n);
  cout << m << ',' << n << endl;
  cout <<"&m=" << &m << ",&n=" << &n << endl;
  print(m);
  print(n);
  print(123);
  print(m+n);//保存在臨時空間,在上面需要加const限制;
  //寫一個函數讓用戶來輸入窗口的信息
  
  Window w;
  input(w);
  print(w);
 }
 //在上面的例子中有多個JiaoHuan函數只是形參類型不同(函數重載);c語言中是沒有的;但是c++,java中有
 //函數形參盡量用引用;數組和基本類型盡量不要用引用。
 //如果不用引用,基本上可以理解為把數值再復制一份,而不是原始數據
 //如果引用不加const,意味著可能要改變引用變量的值
 
 比較下列兩個例子
 #include <iostream>
 using namespace std;
 
 int max(int x,int y)
 {
  return x<y?y:x;
 }
 int main()
 {
  int m=10,n=20;
  max(m,n);//返回的是值而不是變量
 }
 //沒有引用的時候只是把return返回值復制一份回來放到臨時空間中作為結果
 
 
 
 #include <iostream>
 using namespace std;
 
 int& max(int& x,int& y)
 {
  return x<y?y:x;
 }
 int & counter()
 {
  int cnt=0;
  ++cnt;
  return cnt;
 }
 int main()
 {
  int m=10,n=20;
  max(m,n);//返回的是變量
  max(m,n)+=80;
  cout << m << ',' << n << endl;
  counter()=1000;
 }
 
 
 函數可以重載,多個函數可以使用同一個名字,但是必須要通過參數列表能區分是哪個函數
 
 定義3個函數按照特定的格式來輸出數組元素
  int a[5]={11,22,33,44,55};
  print(a,5,); //11 22 33 44 55
  print(a,5,','); //11,22,33,44,55,
  print(a,5,true);//[11 22 33 44 55]
  
 
 #include <iostream>
 using namespace std;
 
 void print(int a[],int n)//extern "C" void printf(int a[],int n)//意思是在編譯的時候不要改變函數的名字
 {
  for (int i=0;i<n;i++)
   cout << a[i] << ' ';
  cout << endl;
 }
 void print(int a[],int n, char sep)
 {
  for(int i=0;i<n;i++)
   cout << a[i] <<sep;//(i=n-1?'\n':sep);
  cout << endl;
 }
 void print(int a[],int n,bool bra)
 {
  if(bra) cout << '[';
  if (n>0) cout << *a;
  for(int i=1;i<n;i++)
   cout << ' ' << a[i];
  if (bra) cout << ']';
  cout << endl;
 }
 
 
 int main()
 {
  int a[5]={11,22,33,44,55};
  print(a,5,); //11 22 33 44 55
  print(a,5,','); //11,22,33,44,55,
  print(a,5,true);//[11 22 33 44 55]
  
 }
 
 
 變更理解
 
 #include <iostream>
 using namespace std;
 
 void print(int a[],int n, char sep)
 {
  if(bra) cout << '[';
  if (n>0) cout << *a;
  for(int i=1;i<n;i++)
   cout << ' ' << a[i];
  if (bra) cout << ']';
  cout << endl;
 }
 void print(int a[],int n)//extern "C" void printf(int a[],int n)//意思是在編譯的時候不要改變函數的名字
 {
  print(a,n,' ',false)
 }

 void print(int a[],int n,bool bra)
 {
  print(a,n,sep,false)
 }
 
 
 int main()
 {
  int a[5]={11,22,33,44,55};
  print(a,5,); //11 22 33 44 55
  print(a,5,','); //11,22,33,44,55,
  print(a,5,true);//[11 22 33 44 55]
  
 }
 
 
 
 
 //可以將以上函數簡化成
 void print(int a[],int n,char sep=' ',bool bra=false)
 {
  
 }
 //c++,函數的形參可以帶默認值,如以上的char sep=' ',bool bra=false;有默認值的形參只能在最后擺放
 //默認值在聲明中指定
 
 
 void f(int);//A
 void f(int,bool=true);//B
 
 f(20);//這樣的話編譯器會報錯。
 
 
 
 #include <iostream>
 using namespace std;
 
 int f(int a){return a*a;}
 int f(int a,int b){return a*b;}
 int main()
 {
  cout << f(10) << endl;
  cout << f(12,34) << endl;
 }
 
 
 inline,經過分析之后做代碼的替換;inline只是一個請求,具體做不做不是他的事
 
 
 宏函數不需要時間和空間,不是真正的函數,而是用一組代碼替換相應的內容;如果參數里面有a++之類的就會異常出錯。
 在c++里面提供了一種更好的處理機制,inline,功能類似宏,但是不是原始替換。===》稱做“內聯函數”
 (機器指令的替換而非代碼的替換)、
 
 c++不提倡用宏,盡量不要用宏。(至少宏里面沒有類型檢查)
 
 
 #include <iostream>
 using namespace std;
 
 inline void f1(){cout << "call f1\n";}
 inline int f2(int n){return n*n; }
 inline int f3(int n){if (n<2) return 1;return n*f3(n-1);}
 int main()
 {
  f1();
  f2(10);
  f3(6);
  cout << f2(10)+f3(6) << endl;
 }
 
 面向過程:關注過程步驟細節
 面向對象:一切以對象為為目標  object-oriented. OOA,OOP,OOD
 
 struct A
 {
  void f(){}
 
 }
 
 
 vi object.cpp
 #include <iostream>
 using namespace std;
 #include <string>
 int main()
 {
  string s="hello world";//string 類,s對象
  //string s("hello world");與上面等價,括號更加方便
  s.replace(2,5,"XXXX");
  s.insert(1,"ilove")
  cout << s << endl;
  //cout.operator <<(s);
 }
 
 vi class.cpp
 #include <iostream>
 #include <string>
 using namespace std;
 
 struct PS{
  string name;
  int age;
  void show(){cout << " i am " << name << ",age" << age <<endl;}
 };//成員默認都是公開的
 class PC{
  string name;
  int age;
 public://可以將其公開
  void show(){cout << " i am " << name << ",age" << age <<endl;}
  PC(const char* n,int a){name=n;age=a;}//與類同名的函數
 };//公開方法,保護數據
 
 int main()
 {
  PS s={"jy",6};//初始化
  PC c("yj",30);//初始化,數據先放到一個PC(const char *n,int a){}函數的形參中
  //PC d;//編譯錯誤,保證對象里面沒有垃圾數據
  //s.name="jy";//可以;//c里面沒有什么私有的,一切都是公開的
  //c.name="yj";//編譯錯誤;不允許直接訪問數據;默認私有的
  s.show();
  c.show();
 }
 
 創建對象只把數據傳到構造函數,
 
 
 
 寫這么一個類
 class Time{
  int h;
  int m;
  int s;
 public:
  Time(){}
  Time(int xs,int fz,int ms){}
  void show();
  void tick();
 }
 
 int main()
 {
  Time t1;
  Time t2(16,23,39);
  t1.tick();
  t2.tick();
  t1.show();
  t2.show();
 }
 
 
 vi time.cpp
 #include <iostream>
 using namespace std;
 class Time{
  int h;
  int m;
  int s;
 public:
  Time(){h=m=s=0;}
  Time(int h,int m,int s){Time::h=h;Time::m=m;Time::s=s;}
  void tick(){
   if(++s>=60){
    s=0;
    if(++m>=60){
     m=0;
     if(++h>=24){
      h=0;
     }
    }
   }
  }
  void show(){
   cout << h<< ':' << m << ':' << s << endl;
  }
 };
 int main()
 {
  Time t1;
  Time t2(16,49,58);
  t1.tick();
  t2.tick();
  t1.show();
  t2.show();
  
 }
 
 
 
 class Date{
  int y,m,d;
 public:
  Date(int y=1970,int m=1,int d=1;)//默認值
  void go();
  void show();
  void input();
  int weekday();
  int difference(Date d2);
  void printMonth();
 }
 
 

 本文由用戶 honghu79 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!