C++解析(8):C++中的新成員
阿新 • • 發佈:2018-12-06
0.目錄
1.動態記憶體分配
- 1.1 C++中的動態記憶體分配
- 1.2 new關鍵字與malloc函式的區別
- 1.3 new關鍵字的初始化
2.名稱空間
- 21 作用域與名稱空間
- 2.2 名稱空間的定義和使用
3.強制型別轉換
- 3.1 C方式的強制型別轉換
- 3.2 C++的新式型別轉換
4.小結
1.動態記憶體分配
1.1 C++中的動態記憶體分配
- C++中通過new關鍵字進行動態記憶體申請
- C++中的動態記憶體申請是基於型別進行的
- delete關鍵字用於記憶體釋放
1.2 new關鍵字與malloc函式的區別
- new關鍵字是C++的一部分
- malloc是由C庫提供的函式
- new以具體型別為單位進行記憶體分配
- malloc以位元組為單位進行記憶體分配
- new在申請單個型別變數時可進行初始化
- malloc不具備記憶體初始化的特性
1.3 new關鍵字的初始化
2.名稱空間
2.1 作用域與名稱空間
在C語言中只有一個全域性作用域:
- C語言中所有的全域性識別符號共享同一個作用域
- 識別符號之間可能發生衝突
C++中提出了名稱空間的概念:
- 名稱空間將全域性作用域分成不同的部分
- 不同名稱空間中的識別符號可以同名而不會發生衝突
- 名稱空間可以相互巢狀
- 全域性作用域也叫預設名稱空間
2.2 名稱空間的定義和使用
C++名稱空間的定義:
C++名稱空間的使用:
使用整個名稱空間:using namespace name;
使用名稱空間中的變數:using name::variable;
使用預設名稱空間中的變數:::variable;
示例:
#include <stdio.h> namespace First { int i = 0; } namespace Second { int i = 1; namespace Internal { struct P { int x; int y; }; } } int main() { using namespace First; using Second::Internal::P; printf("First::i = %d\n", i); printf("Second::i = %d\n", Second::i); P p = {2, 3}; printf("p.x = %d\n", p.x); printf("p.y = %d\n", p.y); return 0; }
執行結果:
[[email protected] Desktop]# g++ test.cpp
[[email protected] Desktop]# ./a.out
First::i = 0
Second::i = 1
p.x = 2
p.y = 3
3.強制型別轉換
3.1 C方式的強制型別轉換
C方式的強制型別轉換:
示例:
#include <stdio.h>
typedef void(PF)(int);
struct Point
{
int x;
int y;
};
int main()
{
int v = 0x12345;
PF* pf = (PF*)v;
char c = char(v);
Point* p = (Point*)v;
pf(5);
printf("p->x = %d\n", p->x);
printf("p->y = %d\n", p->y);
return 0;
}
執行結果:
[[email protected] Desktop]# g++ test.cpp
[[email protected] Desktop]# ./a.out
Segmentation fault (core dumped)
編譯器雖然可以編譯通過,但是無法執行!
存在的問題:
- 過於粗暴——任意型別之間都可以進行轉換,編譯器很難判斷其正確性
- 難於定位——在原始碼中無法快速定位所有使用強制型別轉換的語句
問題:強制型別轉換在實際工程中是很難完全避免的!如何進行更加安全可靠的轉換?
3.2 C++的新式型別轉換
C++將強制型別轉換分為4個不同的型別:
static_cast強制型別轉換——靜態型別轉換
- 用於基本型別間的轉換
- 不能用於基本型別指標間的轉換
- 用於有繼承關係類物件之間的轉換和類指標之間的轉換
const_cast強制型別轉換
- 用於去除變數的只讀屬性
- 強制轉換的目標型別必須是指標或引用
reinterpret_cast強制型別轉換
- 用於指標型別間的強制轉換
- 用於整數和指標型別間的強制轉換
dynamic_cast強制型別轉換——動態型別轉換
- 用於有繼承關係的類指標間的轉換
- 用於有交叉關係的類指標間的轉換
- 具有型別檢查的功能
- 需要虛擬函式的支援
示例:
#include <stdio.h>
void static_cast_demo()
{
int i = 0x12345;
char c = 'c';
int* pi = &i;
char* pc = &c;
c = static_cast<char>(i);
pc = static_cast<char*>(pi); // Error
}
void const_cast_demo()
{
const int& j = 1;
int& k = const_cast<int&>(j);
const int x = 2;
int& y = const_cast<int&>(x);
int z = const_cast<int>(x); // Error
k = 5;
printf("k = %d\n", k);
printf("j = %d\n", j);
y = 8;
printf("x = %d\n", x);
printf("y = %d\n", y);
printf("&x = %p\n", &x);
printf("&y = %p\n", &y);
}
void reinterpret_cast_demo()
{
int i = 0;
char c = 'c';
int* pi = &i;
char* pc = &c;
pc = reinterpret_cast<char*>(pi);
pi = reinterpret_cast<int*>(pc);
pi = reinterpret_cast<int*>(i);
c = reinterpret_cast<char>(i); // Error
}
void dynamic_cast_demo()
{
int i = 0;
int* pi = &i;
char* pc = dynamic_cast<char*>(pi); // Error
}
int main()
{
static_cast_demo();
const_cast_demo();
reinterpret_cast_demo();
dynamic_cast_demo();
return 0;
}
執行結果為:
[[email protected] Desktop]# g++ test.cpp
test.cpp: In function ‘void static_cast_demo()’:
test.cpp:11: error: invalid static_cast from type ‘int*’ to type ‘char*’
test.cpp: In function ‘void const_cast_demo()’:
test.cpp:22: error: invalid use of const_cast with type ‘int’, which is not a pointer, reference, nor a pointer-to-data-member type
test.cpp: In function ‘void reinterpret_cast_demo()’:
test.cpp:47: error: invalid cast from type ‘int’ to type ‘char’
test.cpp: In function ‘void dynamic_cast_demo()’:
test.cpp:54: error: cannot dynamic_cast ‘pi’ (of type ‘int*’) to type ‘char*’ (target is not pointer or reference to class)
將出錯的幾行程式碼註釋後:
#include <stdio.h>
void static_cast_demo()
{
int i = 0x12345;
char c = 'c';
int* pi = &i;
char* pc = &c;
c = static_cast<char>(i);
//pc = static_cast<char*>(pi); // Error
}
void const_cast_demo()
{
const int& j = 1;
int& k = const_cast<int&>(j);
const int x = 2;
int& y = const_cast<int&>(x);
//int z = const_cast<int>(x); // Error
k = 5;
printf("k = %d\n", k);
printf("j = %d\n", j);
y = 8;
printf("x = %d\n", x);
printf("y = %d\n", y);
printf("&x = %p\n", &x);
printf("&y = %p\n", &y);
}
void reinterpret_cast_demo()
{
int i = 0;
char c = 'c';
int* pi = &i;
char* pc = &c;
pc = reinterpret_cast<char*>(pi);
pi = reinterpret_cast<int*>(pc);
pi = reinterpret_cast<int*>(i);
//c = reinterpret_cast<char>(i); // Error
}
void dynamic_cast_demo()
{
int i = 0;
int* pi = &i;
//char* pc = dynamic_cast<char*>(pi); // Error
}
int main()
{
static_cast_demo();
const_cast_demo();
reinterpret_cast_demo();
dynamic_cast_demo();
return 0;
}
執行結果為:
[[email protected] Desktop]# g++ test.cpp
[[email protected] Desktop]# ./a.out
k = 5
j = 5
x = 2
y = 8
&x = 0x7ffd5a6a5650
&y = 0x7ffd5a6a5650
4.小結
- C++中內建了動態記憶體分配的專用關鍵字
- C++中的動態記憶體分配可以同時進行初始化
- C++中的動態記憶體分配是基於型別進行的
- C++中名稱空間概念用於解決名稱衝突問題
- C方式的強制型別轉換
- 過於粗暴
- 潛在的問題不易被發現
- 不易在程式碼中定位
- 新式型別轉換以C++關鍵字的方式出現
- 編譯器能夠幫助檢查潛在的問題
- 非常方便的在程式碼中定位
- 支援動態型別識別( dynamic_cast )