1. 程式人生 > 其它 >初識C++以及C++對C的增強和擴充套件

初識C++以及C++對C的增強和擴充套件

技術標籤:# C++基礎c++c語言

初識C++以及C++對C的增強和擴充套件

1 C++ 概述

1.1 C++兩大程式設計思想

1. 面向物件
2. 泛型程式設計

1.2 C++移植性和標準

  1. ANSI在1998制定出C++第一套標準(C++98)

2 初識C++

2.1 面向物件的三大特性

封裝、繼承、多型

2.2 標頭檔案以及標準名稱空間

#include <iostream>		// 標準輸入輸出流
using namespace std;	// 標準名稱空間

2.3 雙冒作用域運算子

::			// 雙冒作用域運算子

std::cout;	// std作用域下的cout

::a;		// ::前面什麼都不新增 代表全域性作用域

2.4 namespace名稱空間

  1. 名稱空間的用途?

解決名稱衝突問題

  1. 名稱空間下可以存放什麼?

變數、函式、結構體、類…

  1. 名稱空間必須要宣告在全域性作用域

  2. 名稱空間可以巢狀命名空

namespace A
{
	int a_;

	namespace B
	{
		int a_;
	}
}

int a = A::a_;		// 名稱空間A下的a_
int a = A::B::a_;	// 名稱空間A中名稱空間B下的a_
  1. 名稱空間是開放的,可以隨時將新成員新增到名稱空間下
namespace A
{
	int a_;
}
namespace B
{
	int b_;
}
namespace
A { int c_; } // 相當於 namespace A { int a_; int c_; }; namespae B { int b_; }
  1. 名稱空間可以匿名的
namespace
{
	int a_ = 100;
	int b_ = 10;
	// 相當於寫了static int a_ = 100; static int b_ = 10;
}
// 相當於全域性變數,直接使用
cout << "a_ = " << a_ << " b_ = " << b_ << endl;
  1. 名稱空間可以起別名
namespace longName
{
	int a_ = 100;
}

void test()
{
	// 名稱空間起別名
	namespace lN = longName;
	cout << "a_ = " << lN::a_ << endl;
}

2.5 using宣告以及using編譯指令

2.5.1 using宣告

1.using 名稱空間名::成員名;
2.當使用using宣告去聲明瞭一個名稱空間中的變數,在函式中有一個相同的變數名,會報錯,儘量避免

namesapce Person
{
	int age_ = 18;
}

void test()
{
	// using 宣告
	using Person::age_;
	
	// 與using宣告的名稱空間Person中的age_變數名相同,會報錯
	int age_ = 20;	

	
	// 此處,因為函式中有age_變數,所以即使聲明瞭名稱空間Person, 下方列印仍然輸出age_ = 20(就近原則)
	cout << "age_ = " << age_ << endl;
}

2.5.1 using編譯指令

1.using namespace 名稱空間名;
2.當using編譯指令 與 就近原則同時出現,優先使用就近原則
3.當using編譯指令有多個,需要加作用域 區分

namespace Person
{
	int age_ = 18;
}
namespace Dog
{
	int age_ = 5;
}

// 第一種情況
void test1()
{
	// using編譯指令宣告名稱空間
	using namespace Person;
	
	// 與using編譯指令宣告的名稱空間Person中的age_變數名相同
	int age_ = 20;

	//此處,因為函式中有age_變數,所以即使使用了using編譯指令宣告名稱空間Person, 下方列印仍然輸出age_ = 20(就近原則)
	cout << "age_ = " << age_ << endl;
}

// 第二種情況
void test2()
{
	// using編譯指令宣告名稱空間
	using namespace Person;
	using namespace Dog;
	
	//此處,因為Person名稱空間和Dog名稱空間都有age_變數, 所以下方列印需要加作用域
	cout << "Person::age_ = " << Person::age_ << endl;	// age_ = 18
	cout << "Dog::age_ = " << Dog::age_ << endl;	// age_ = 5
}

3 C++對C語言增強以及擴充套件

3.1 全域性變數檢測增強

int a;
int a = 10;
// 在C語言中,可以這樣使用,相當於賦值 int a; a = 10;
// 在C++語言中,編譯錯誤

3.2 函式檢測增強

C語言:返回值沒有檢測 形參型別沒有檢測 函式呼叫引數個數沒有檢測
C++語言:返回值檢測、形參型別檢測、函式呼叫引數個數

// 在C語言中
// 1	函式的返回值沒有檢測
// 2	形參型別沒有檢測
// 3	函式呼叫引數個數沒有檢測
getRectS( w  , h)
{
	return w *h;
}
void test()
{
	printf("%d\n", getRectS(10, 10, 10));
}

3.3 型別轉換檢測增強

C語言:char * p = malloc(64);
C++語言:char * p = (char *)malloc(64);

// malloc返回型別為void*,在C語言中可以這樣使用
void test()
{
	char * p = malloc(64);
}
// 在C++語言中必須強轉
void test()
{
	char * p = (char *)malloc(64);
}

3.4 struct 增強

C語言:結構體中不可以有函式,建立結構體變數不可以簡化struct
C++語言:結構體中可以有函式,建立結構體變數可以簡化struct

struct Person
{
	int age_;
	//void func(); C語言下 結構體中不可以有函式
};
// 1.C++可以在結構體中放函式

// 2.建立結構體變數,可以簡化關鍵字struct
void test()
{
	struct Person p1;	// c
	Person p2;			// c++
}

3.5 bool資料型別擴充套件

C++才有bool型別

// C++才有bool型別
// 代表真 --- 1 true  假 ---- 0 false
bool flag;	// true/false

3.6 三目運算子增強

C語言:返回的是值,只能做左值
C++語言:返回的是變數,可以做左值,也可以做右值

int a = 10;
int b = 20;
int c;
//C語言下返回的是值,只能做左值
c = a > b ? a : b;		// c = 20
// a > b ? a : b = 100  相當於 20 = 100; 錯誤
*(a > b ? &a : &b) = 100;	// b = 100

//C++語言下返回的是變數,可以做左值,也可以做右值
a > b ? a : b = 100;	// 返回b, b = 100;

3.7 const增強

C語言:

  1. 全域性 const 直接修改->失敗 ,間接修改(通過指標) ->語法通過,執行失敗
  2. 區域性 const 直接修改 ->失敗 ,間接修改(通過指標)-> 成功
  3. int arr[A]; 在C語言下 const是偽常量,不可以初始化陣列

C++語言:

  1. 全域性 const 和C結論一樣
  2. 區域性 const 直接修改->失敗 ,間接修改(通過指標)-> 失敗
  3. int arr[B]; C++中const可以稱為常量,可以初始化陣列
// C語言下
// 全域性const   直接修改 失敗  間接修改(通過指標)  語法通過,執行失敗
// 區域性 const  直接修改 失敗  間接修改(通過指標)  成功
// int arr[A]; 在C語言下 const是偽常量,不可以初始化陣列

const int A = 20;	// 全域性
void test1()
{
	// 1.全域性
/*
	// 直接修改失敗
	A = 100;
	// 間接修改失敗	
	int *p = &A;
	*P = 40;
*/

	// 2.區域性
	const int B = 10;	// 區域性
	// B = 30;	// 直接修改失敗

	// 間接修改成功
	int *p = &B;	
	*p = 100;		// B = 100
}

// C++語言下
// 全域性 const  和C結論一樣
// 區域性 const  直接修改失敗 間接修改(通過指標) 失敗  
// C++中const可以稱為常量,可以初始化陣列
const int C = 20;	// 全域性
void test2()
{
	// 1.全域性
/*
	// 直接修改失敗
	C = 100;
	// 間接修改失敗	
	int *p = &C;
	*P = 40;
*/

	// 2.區域性
/*
	const int D = 10;	// 區域性
	// 直接修改失敗
	D = 30;	

	// 間接修改失敗
	int *p = &D;	
	*p = 100;	
	// 相當與int temp = D; int *p = &temp;	*p = 100;(temp = 100)
	// 修改的是一個臨時變數的值,實際上D的值沒有被修改
*/
}

4 const 連結屬性

C語言下 const修飾的全域性變數預設是外部連結屬性
C++下 const修飾的全域性變數預設是內部連結屬性,可以加extern 提高作用域

// test.cpp 檔案
// C語言中
const int g_a = 100;

// C++語言中
extern const int g_b = 100;//預設是內部連結屬性 可以加關鍵字 extern 提高作用域
// 使用全域性變數g_a,C和C++一樣
void test()
{
	extern const int g_a;
	
	printf("%d\n", g_a);	
}

5 const 分配記憶體情況

  1. 對const變數取地址 ,會分配臨時記憶體
  2. 使用普通變數來初始化const變數,棧記憶體(可通過間接方式修改const變數)
  3. 對於自定義資料型別,棧記憶體(可通過間接方式修改const變數)
//1、對const變數取地址,會分配臨時記憶體  
void test01()
{
	const int a = 10;
	int * p = (int *)&a;
	// 相當於 int tmp = a;	int *p = &tmp;
}
//2、使用普通變數來初始化const變數
void test02()
{
	int a = 10;			// 棧記憶體
	const int b = a;	// 棧記憶體

	int *p = (int *)&b;
	*p = 1000;			// a =100, b = 1000
}
//3、對於自定義資料型別 
struct Person
{
	string m_Name;
	int m_Age;
};
void test03()
{
	const Person p;		// 棧記憶體
	
	Person * pp = (Person *)&p;
	(*pp).m_Name = "Tom";	// p.m_Name為Tom
	pp->m_Age = 10;			// p.m_Age = 10
}

6 擴充套件閱讀

儘量用const代替define
define出的巨集常量,沒有資料型別、不重視作用域(不進行編譯,在預處理階段展開)

#difine FLAG 10

// 用const代替define
const int FLAG = 10;