文章目錄
- 一、頭檔案與命名空間
-
- 1. 頭檔案是什麼
- 2.幾個特殊情況
- 3.命名空間
- 二、面向對象程式設計
-
- 1.文法點
-
- 1.1 private、public、protected
- 1.2 inline
- 1.3 const
- 1.4 static
- 1.5 friend
- 2.面向對象的難點問題
-
- 2.1 構造函數
- 2.2 操作符重載問題
- 2.3 copy問題
- 2.4 析構函數問題
- 2.5 值、指針、引用
-
- 2.5.1 value 與 reference
- 2.5.2 reference 與 pointer
- 二、示例
-
- 1.類不含指針(Complex)
- 2.類含指針(String)
一、頭檔案與命名空間
1. 頭檔案是什麼
例:A.cpp, A.h, B.cpp
A.h 頭檔案 中寫入類聲明、函數原型、#define;
A.cpp實作檔案 寫入類函數的定義實作;
B.cpp調用檔案 通過一個宏指令 “#include” 調用A.h中的類和函數等
[注1] 頭檔案無需編譯,隻需在源檔案預處理時被合并
[注2]#include功能僅是簡單的文本替換
[注3]系統頭檔案用< >, 自定義頭檔案用" "
//頭檔案的防禦式程式設計
#ifndef A_H
#define A_H
//...
#endif
2.幾個特殊情況
(1)static修飾變量、函數可以寫在.h檔案中
(2)inline内聯函數定義可以寫在.h檔案中
(3)模闆類型可以寫在.h中,模闆在調用時才編譯
3.命名空間
區分不同庫中相同名稱的函數、類、變量
- 定義
namespace namespace_name {
// 代碼聲明
}
- 調用
//後續的代碼将使用指定的命名空間中的名稱。
using namespace namespace_name;
//指定命名空間中的特定項目
using std::cout;
二、面向對象程式設計
1.文法點
1.1 private、public、protected
(1)資料防止洩露,通常為private。
(2)protected可由派生類通路。
(3)同一類的不同對象可以互相通路private變量、函數。
1.2 inline
(1)内聯函數的兩種寫法:
- 定義寫在類内
- 定義寫在類外,加上inline字首
(2)内聯函數隻是一種建議,具體實作由編譯器決定
(3)内聯函數減少了運作棧儲存變量的開銷
1.3 const
(1)const成員變量:不應被改變
(2)const成員函數:不應改變成員變量的值
(3)const對象:隻能通路被 const 修飾的成員函數、變量
(4)const int* p與int* const p
1.4 static
static類型屬于類,對象間共享記憶體
(1)static成員變量
(2)stattic成員函數
- 隻能通路靜态成員變量
- 聲明時加static,定義時不加static
1.5 friend
【友元函數】
(1)友元函數不是類的成員函數,在類中聲明,類外定義
(2)友元函數有權通路類的private、protected、public函數和變量。
(3)友元函數必須通過參數傳遞對象才能通路類的成員
【友元類】
(1)友元類中的所有成員函數都是另外一個類的友元函數。
2.面向對象的難點問題
2.1 構造函數
- 初始化問題
提前初始化,而不是用assign指派有利于提高性能。complex(double r, double i):re(r),im(i) {}
- 構造函數可以重載
- private中的構造函數:單例模式
2.2 操作符重載問題
-
操作符重載的兩種方法
成員函數方法:a.op(b),含有傳回值滿足連續op的情況;
全局函數+友元函數方法:op(a,b);
- 不能重載的操作符
.
?:
::
sizeof
- 運算符重載不改變優先級
2.3 copy問題
-
深拷貝 和 淺拷貝
淺拷貝:類内變量建立副本,類内指針共享記憶體
深拷貝:需要自定義重載
- 預設拷貝為淺拷貝,含指針的類可能出現記憶體洩露
-
拷貝構造copy ctor 和 拷貝指派copy op=
copy op= 等價于 自我指派檢測 + delete_self + copy ctor
2.4 析構函數問題
- 類記憶體在動态配置設定記憶體的情況時(往往表現為含指針),需要添加析構函數
- 普通對象:消亡時自動調用析構函數
- 指針對象:注意new與delete的比對問題
2.5 值、指針、引用
2.5.1 value 與 reference
- value:預設為淺拷貝,記憶體開銷大
- reference:變量别名,共享記憶體
- 傳回局部變量時,不能聲明為reference,因為局部變量在函數結束時銷毀
2.5.2 reference 與 pointer
- pointer可能為null,reference必須被初始化
- pointer可以改變,reference不能更改
二、示例
1.類不含指針(Complex)
代碼如下(示例):
#include<iostream>
using namespace std;
class Complex{
private:
double real, imag;
public:
//預設構造函數
Complex(){ }
//重載構造函數 + 初始化清單
Complex(double r, double i): real(r), imag(i){ }
//成員函數 的 操作符重載 + 臨時對象
Complex operator+(const Complex& c) const{
//傳回local變量不能使用reference
return Complex(real + c.real, imag + c.imag);
}
//全局函數 的 操作符重載 + 友元函數
friend ostream& operator<<(ostream& os, Complex& c);
friend Complex& operator+=(Complex& c1, const Complex& c2);
/*
Complex& operator+=(const Complex& c2)
{
this->real += c2.real;
this->imag += c2.imag;
}
*/
};
Complex& operator+=(Complex& c1, const Complex& c2){
c1.real += c2.real;
c1.imag += c2.imag;
return c1;
}
ostream& operator<<(ostream& os, Complex& c){
os << "(" << c.real << "," << c.imag << ")";
return os;
}
int main()
{
Complex c1;
Complex c2(5,5);
const Complex c3(5,5);
c2 += c3;
c1 = c2 + c3;
cout<<c1<<endl;
}
2.類含指針(String)
代碼如下(示例):
#include<iostream>
#include<cstring>
/*
注:
cstring:c++版的string.h
string: stl範疇
string.h: c語言庫,c++相容
*/
using namespace std;
class String{
private:
char* m_data;
public:
String(const char* cstr = 0);
//copy ctor
String(const String& s);
//copy op=
String& operator=(const String& s);
//析構函數
~String();
char* get_str() const{
return m_data;
}
friend ostream& operator<<(ostream& os, const String& s);
};
//注:不能同時在 聲明 和 定義 中寫預設參數
inline
String::String(const char* cstr){
if(cstr){
m_data = new char[strlen(cstr) + 1];
strcpy(m_data, cstr);
}
else{
m_data = new char[1];
*m_data = '\0';
}
}
inline
String::~String(){
delete[] m_data;
}
inline
String::String(const String& s){
//深拷貝
m_data = new char[ strlen(s.m_data) + 1 ];
strcpy(m_data, s.m_data);
}
inline
String& String::operator=(const String& s){
//step1:檢查自我指派
//注意指針細節:&s,this:位址;s,*this:string内容
if(&s == this){
return *this;
}
//step2:删除空間
delete[] m_data;
//step3:copy ctor
m_data = new char[ strlen(s.m_data) + 1 ];
strcpy(m_data, s.m_data);
return *this;
}
ostream& operator<<(ostream& os, const String& s)
{
os<<s.get_str();
return os;
}
int main()
{
const String s2("duan");
const String s3("shuai");
String s1(s2);
cout<<s1<<endl;
s1 = s3;
cout<<s1<<endl;
}