C++筆記、重要知識、易錯點

讓C++控制檯程序停下來,實現暫停功能

一、針對Windows

#include <stdlib.h>
system( "PAUSE ");   //第一種方式
getchar();           //第二種方式,這招對QT程序也有用
sleep();             //第三種方式

二、針對Linux

getchar();

字符串

  1. 字符數組
char a[10] = {'h','e','l','l','o'};
char b[] = "hello";
  1. 字符指針
char *d = "hello";
cout<<d<<endl;   // hello
cout<<*d<<endl;  // h

全局變量

用extern聲明全局變量
//file1.cpp
int a = 1; //定義全局變量a
//file2.cpp
extern int a; //聲明全局變量a,代表其他文件已經定義了變量a
//file3.cpp
int a = 3; //重複定義全局變量a,報錯

用static私有和靜態持續
//file1.cpp
static int a = 1; //全局變量a是私有的,只在file1.cpp文件中可見
//file2.cpp
int a = 2; //不會出現重複定義的錯誤

void func()
{
   static int count = 0; 
   count++;
   cout<<count<<endl;
} //局部變量count是持續的,當函數調用結束,變量count依然存在,
  //當下一次函數被調用,count的 初始值爲上次結束的值

函數不允許內部嵌套定義函數,所以所有函數都是全局的
static void g_func(); //該函數只在本文件可見,注意,聲明時也需要加static關鍵字


namespace名字空間

namespace Circle {
	int a;     //定義變量
	void f();  //聲明函數
	struct A {...};   //定義結構體
	}
	
namespace Square{
	int a;     //定義變量a,此處不和Circle名字空間的a衝突
    }
    
Circle::a = 1;
Circle::f();
Circle::A aa;
using namespace Circle;
cout << a <<endl;  //Ok, 打印Circle中的a
using namespace Circle;
using namespace Square;
cout << a <<endl;  //錯誤,不知道是哪個名字空間的a
cout << Circle::a<<endl; //Ok

總結

  1. 局部作用域的變量超出代碼塊就會消亡
  2. 避免使用全局變量,全局變量不能重複定義
  3. static關鍵字的兩個含義:私有和持續性
  4. namespace可以嵌套
  5. 名稱空間不要在.h文件中使用,儘可能在局部代碼塊中使用

常量指針與指針常量

常量指針:常量指針表示一個指針指向的變量爲常量即帶有const屬性;例如:const int * p 或者int const * p
指針常量:表示一個指針本身爲常量即指針本身帶有const屬性;例如:int* const p
常量指針指向的對象由於有const屬性,無法直接改變,但是指針本身值(即指針指向的內存地址)可以改變
指針常量則是指針本身有const屬性, 指針的值(即指針指向的內存地址)無法直接改變,而該地址內的變量可以改變。
//*************************************************************************************
//引用和指針常量在聲明時就必須初始化
//臨時變量和const引用傳參

double cube(double &a)
{
   return a*a*a;
}
double x=1.0;
long y = 2;
cube(x);   //ok
cube(x+1)  //錯誤
cube(2)    //錯誤
cube(y)    //錯誤
//****************************************
double cube(const double &a)
{
   return a*a*a;
}
double a = 3.0; 
int b = 3;
cube(a-1.0); //臨時變量
cube(2.0);   //臨時變量 
cube(b);     //臨時變量

注意

  1. 基本數據類型,無需修改, 按值傳遞
  2. 基本數據類型,需要修改, 指針傳遞(更直觀)
  3. 數組, 指針傳遞(唯一選擇,數組不能用引用傳遞)
  4. 結構或者類,無需修改, const引用傳遞
  5. 結構或者類,需要修改, 引用傳遞

struct和class的用法幾乎一樣,就是默認的訪問方式不同
struct默認是public, class是默認private
struct之前在c語言中只能定義變量,不能定義函數;在c++中才被擴展爲可以定義函數


友元(friend)是單向的,也是不能傳遞的 (儘量少用友元,它打破了c++的數據封裝性)
友元函數:friend + 函數聲明;
友元類: friend + 類聲明;


類中的成員變量爲數組時,數組不能用初始化列表進行初始化,必須寫一個構造函數對數組元素一個一個的初始化。
類的析構函數只有一個,參數列表是空的
構造函數可以是私有的,但析構函數必須是公有的,方便外界調用


靜態成員變量:用static關鍵字修飾的成員變量,無論有多少個對象,都只被創建一次,對象之間共用這個靜態變量,具有持續性,生命週期爲整個程序的生命週期。
靜態成員變量的初始化必須在類外。
靜態成員函數(對象之間共享)不能直接訪問類的非靜態成員變量。


在類對象按值傳遞或者函數返回類對象時,會調用拷貝構造函數
默認的拷貝構造函數只拷貝非靜態成員變量,而不會改變靜態成員變量,也不會爲指針重新分配空間


C++特點:數據抽象,封裝,繼承,多態
根據對象類型選擇需要調用的函數是動態綁定(晚期綁定),動態綁定的函數,需要在基類的該函數前面加上關鍵字virtual(指定該函數爲虛函數)
注意

  1. 構造函數不能是虛函數
  2. 析構函數應當是虛函數
    virtual ~Rect{} Rect *rect = new Square(3); delete rect;
  3. 在派生類中重新定義相同函數名的方法會隱藏基類方法
    int Square:: getArea(int i) {....} square.getArea(); //無法調用基類中無參數的getArea函數,出錯

多態的概念:一個接口,多種實現方法
虛函數virtual
靜態綁定(早期綁定):在編譯的時候決定的
動態綁定(晚期綁定):在程序運行的時候決定的


純虛函數:virtual float getArea()=0;
沒有函數體;“=0”不是返回值爲0,只是一個形式作用;是一個聲明語句,需要分號結尾;必須在派生類中實現。
包含純虛函數的基類叫抽象基類,不能被實例化。
基類的析構函數必須實現,因爲當派生類析構時會調用
純虛析構函數和其他純虛函數不同,在基類中是必須實現的


使用抽象基類的原因:

  1. 一些基類被實例化是不合理的
  2. 使用抽象基類和純虛函數,可以方便地使用多態特性,利用基類去調用派生類的方法
  3. 抽象基類分離了函數接口和具體的實現

C++中默認參數在聲明還是定義(實現)中確定?
答:聲明是用戶可以看到的部分,客戶非常信任地使用這些特性,希望得到一定的結果,但是如果在實現中使用了不同的缺省值,那將是災難性的。因此編譯器禁止聲明和定義同時定義缺省參數值。(函數也叫接口,是需要用戶調用的,需要用戶能看到這些缺省參數值)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章