初識C++以及C++對C的增強和擴充套件
阿新 • • 發佈:2020-12-31
初識C++以及C++對C的增強和擴充套件
1 C++ 概述
1.1 C++兩大程式設計思想
1. 面向物件
2. 泛型程式設計
1.2 C++移植性和標準
- 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名稱空間
- 名稱空間的用途?
解決名稱衝突問題
- 名稱空間下可以存放什麼?
變數、函式、結構體、類…
-
名稱空間必須要宣告在全域性作用域
-
名稱空間可以巢狀命名空
namespace A
{
int a_;
namespace B
{
int a_;
}
}
int a = A::a_; // 名稱空間A下的a_
int a = A::B::a_; // 名稱空間A中名稱空間B下的a_
- 名稱空間是開放的,可以隨時將新成員新增到名稱空間下
namespace A
{
int a_;
}
namespace B
{
int b_;
}
namespace A
{
int c_;
}
// 相當於
namespace A
{
int a_;
int c_;
};
namespae B
{
int b_;
}
- 名稱空間可以匿名的
namespace
{
int a_ = 100;
int b_ = 10;
// 相當於寫了static int a_ = 100; static int b_ = 10;
}
// 相當於全域性變數,直接使用
cout << "a_ = " << a_ << " b_ = " << b_ << endl;
- 名稱空間可以起別名
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語言:
- 全域性 const 直接修改->失敗 ,間接修改(通過指標) ->語法通過,執行失敗
- 區域性 const 直接修改 ->失敗 ,間接修改(通過指標)-> 成功
- int arr[A]; 在C語言下 const是偽常量,不可以初始化陣列
C++語言:
- 全域性 const 和C結論一樣
- 區域性 const 直接修改->失敗 ,間接修改(通過指標)-> 失敗
- 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 分配記憶體情況
- 對const變數取地址 ,會分配臨時記憶體
- 使用普通變數來初始化const變數,棧記憶體(可通過間接方式修改const變數)
- 對於自定義資料型別,棧記憶體(可通過間接方式修改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;