前幾天面試寧波銀行的時候面試官問:C和C++的區別是什麼?什麼是OOP?
靚仔語塞。。。。
C是程序導向的語言,C++是物件導向的語言
OOP(物件導向(工資)程式設計) OOD(物件導向的設計),OOA(物件導向的分析)
舉個最簡單點的例子來區分 程序導向和麪向物件
有一天你想吃魚香肉絲了,怎麼辦呢?你有兩個選擇
1、你要自己去準備原材料。
2、去飯店!
看出來區別了嗎?這就是1是程序導向,2是物件導向。
物件導向有什麼優勢呢?首先你不需要知道魚香肉絲是怎麼做的。如果你突然不想吃魚香肉絲了,想吃別的菜,對於1需要重新買菜,買調料什麼的。對於2,老闆!那個魚香肉絲換成洛陽白菜吧,提高了可維護性。
OOP私自昂的三大特徵:封裝、繼承、多型
C++使用new和delete來開闢和釋放空間
重定位new: 在new和型別之間加一個地址,表示在棧上的這個變數的某一個位元組開闢一片自由儲存區
int a;
在a的記憶體單元中選擇一個記憶體單元儲存a
(重點!!!面試必問)new和malloc 的區別
1、malloc的返回值不安全需要進行型別轉換,而new不需要。
2、new是一個關鍵字、malloc是一個函數
3、malloc需要使用者輸入開闢記憶體的位元組大小,呢問,不需要計算開闢記憶體的大小。
4、new開闢記憶體失敗拋出bad_alloc異常,malloc開闢記憶體失敗返回空指針
5、malloc在堆上開闢記憶體,new開闢的空間叫做自由儲存區。
6、malloc只能開闢空間不負責初始化,new不僅可以開闢空間還可以初始化
7、開闢動態陣列的時候new [i] 而malloc(總位元組數)
爲什麼不直接操作堆記憶體,而是通過指針指向簡介操作?
動態開闢的堆記憶體沒有變數名,只能把堆記憶體的所有權交給棧上一個有變數名的指針來進行管理
穿插一個問題:堆和棧的區別是什麼?
1.棧:由操作系統自動分配釋放 ,存放函數的參數值,區域性變數的值等。其操作方式類似於數據結構中的棧;
堆: 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由OS回收,分配方式倒是類似於鏈表。
2、數據結構:堆可以看作一棵樹,而棧是一種先進後出的數據結構。
建構函式:在建立物件的時候初始化物件。
解構函式:在物件生命週期到達用來復原物件。
建構函式和解構函式的名字和類名一樣、沒有返回值
在建構函式中也可以用初始化列表
我們先實現一個簡單的回圈佇列
class Queue
{
public:
Queue(int size1 = 20)
{
_pQue = new int[size1];
front = rear = 0;
size = size1;
}
~Queue()
{
delete[]_pQue;
_pQue = nullptr;
}
void push(int val)
{
if (full())
resize();
_pQue[rear] = val;
rear = (rear + 1) % size;
}
void pop()
{
if (empty())
{
return;
}
front = (front + 1) % size;
}
int top()//獲取隊頭元素
{
return _pQue[front];
}
bool full() { return (rear + 1) % size == front; }
bool empty() {
return front == rear;
}
void resize()
{
int *ptmp = new int[size * 2];
int index = 0;
for (int i = front;i != rear;i = (i + 1) % size)
{
ptmp[index++] = _pQue[i];
}
delete[]_pQue;
_pQue = ptmp;
front = 0;
rear = index;
size *= 2;
ptmp = nullptr;
}
Queue(const Queue &src)
{
size = src.size;
front = src.front;
rear = src.rear;
_pQue = new int[size];
for (int i = front;i != rear;i = (i + 1) % size)
_pQue[i] = src._pQue[i];
}
Queue& operator = (const Queue &src)
{
if (this == &src)
{
return *this;
}
delete[]_pQue;
size = src.size;
front = src.front;
rear = src.rear;
_pQue = new int[size];
for (int i = front;i != rear;i = (i + 1) % size)
_pQue[i] = src._pQue[i];
return *this;
}
private:
int *_pQue;//申請佇列的陣列空間
int front;//對頭
int rear;//隊尾元素的後繼位置
int size;
};
int main()
{
Queue si;
for (int i = 0;i < 20;++i)
{
si.push(rand() % 100);
}
while (!si.empty())
{
cout << si.top() << endl;
si.pop();
}
Queue s2 = si;
si.resize();
getchar();
return 0;
}
在動態開闢的陣列進行拷貝的時候進行拷貝的時候發生淺拷貝問題,隨後在解構函式中呼叫delete時出現錯誤。
下面 下麪手寫一個深拷貝的String類
class String
{
public:
String(const char *str = nullptr)
{
if (str != nullptr)
{
m_data = new char[strlen(str) + 1];
strcpy(this->m_data, str);
}
else
{
m_data = new char[1];
*m_data = '\0';
}
}
String(const String &other)
{
m_data = new char[strlen(other.m_data) + 1];
strcpy(this->m_data, other.m_data);
}
~String(void)
{
delete[]m_data;
}
String& operator = (const String &other)
{
//返回this的參照,即返回this本身
if (this == &other)
{
return *this;
}
delete[]m_data;
m_data = new char[strlen(other.m_data) + 1];
strcpy(this->m_data, other.m_data);
return *this;
}
private:
char *m_data;
};
int main()
{
String str1;
String str2("hello");
return 0;
}