C++ 完全兼容C
一 創建一個簡單的C++類項目
1 源文件和頭文件分開:
- 右鍵項目-在文件資源管理器中打開文件夾
- 項目文件夾下創建兩個文件夾(如:ConsoleApplication1\ConsoleApplication1 下 新建include、src文件夾)
- 頭文件-添加現有項-選擇include文件夾-創建一個.h文件,添加新的cpp文件到src目錄
- 屬性-C/C+± 常規- 附加包含目錄-選擇新建的.h文件夾(如include)-應用-確定
2 創建一個C++類
Teacher.h中聲明
#pragma once
class MyTeacher
{
public:
MyTeacher(); //構造函數 (malloc)
~MyTeacher();//析構函數 釋放在構造函數裏面動態申請的內存 (free)
void setAge(int age);
int getAge();
void setName( char *name);
char* getName();
private:
int age;
char *name;
};
Teacher.cpp 引入頭文件並實現
::代表限定符代表類的方法,如果不寫,則是cpp中的方法
#pragma once
#include <Teacher.h>
#include <iostream>
//c++ 標準庫的命名空間
using namespace std;
MyTeacher::MyTeacher() {
cout << " MyTeacher 構造函數 地址:" << this << endl;
}
MyTeacher::~MyTeacher() {
cout << " MyTeacher 析構函數 地址:" << this << endl;
}
// ::代表限定符
void MyTeacher::setAge(int age) {
this->age = age;
}
int MyTeacher::getAge() {
return this->age;
}
void MyTeacher::setName(char *name) {
cout << " MyTeacher setName" << name << endl;
this->name = name;
}
char* MyTeacher::getName() {
return this->name;
}
main.cpp使用
#include <Teacher.h>
#include <iostream>
using namespace std;
void fun() {
MyTeacher teacher;
teacher.setAge(18);
teacher.setName("張三");
cout << "teacher name: " << teacher.getName() << endl;
cout << "teacher age: " << teacher.getAge() << endl;
}
void main() {
fun();
system("pause");
}
結果:
MyTeacher 構造函數 地址:00B3F9B0
teacher name: 張三
teacher age: 18
MyTeacher 析構函數 地址:00B3F9B0
二 引用
引用是C++定義的一種新類型
//聲明形參爲引用
void change(int& i) {
i = 10;
}
int i = 1;
change(i);
printf("%d\n",i); //i == 10
引用和指針是兩個東西
引用 :變量名是附加在內存位置中的一個標籤,可以設置第二個標籤
簡單來說 引用變量是一個別名,表示一個變量的另一個名字
三 值傳遞和引用傳遞
定義一個方法,能夠將Teacher的名稱和年齡替換
1 值傳遞
//替換teacher java 肯定能夠成功
//爲什麼這裏只調用了析構函數,沒有調用構造函數?
//值傳遞 存在值拷貝
void setFunc(MyTeacher teacher) {
teacher.setAge(31);
teacher.setName("yuehan");
cout << "setFunc teacher name: " << teacher.getName() << endl;
cout << "setFunc teacher age: " << teacher.getAge() << endl;
}
調用
void main() {
MyTeacher teacher;
teacher.setAge(18);
teacher.setName("張三");
cout << "teacher name: " << teacher.getName() << endl;
cout << "teacher age: " << teacher.getAge() << endl;
setFunc(teacher);
cout << "teacher name: " << teacher.getName() << endl;
cout << "teacher age: " << teacher.getAge() << endl;
system("pause");
}
輸出結果:
MyTeacher 構造函數 地址:0115FED4
teacher name: 張三
teacher age: 18
setFunc teacher name: yuehan
setFunc teacher age: 31
MyTeacher 析構函數 地址:0115FDF8
teacher name: 張三
teacher age: 18
結果分析: Teacher的name和age沒有被替換,setFunc只調用了析構函數沒有調用構造函數
2 引用傳遞
//引用傳遞
//c++ 引用 是內存空間的別名 不存在拷貝 只傳遞內存別名
void setFuncY(MyTeacher &teacher) {
teacher.setAge(31);
teacher.setName("yuehan");
cout << "setFunc teacher name: " << teacher.getName() << endl;
cout << "setFunc teacher age: " << teacher.getAge() << endl;
}
調用:
void main() {
MyTeacher teacher;
teacher.setAge(18);
teacher.setName("張三");
cout << "teacher name: " << teacher.getName() << endl;
cout << "teacher age: " << teacher.getAge() << endl;
setFuncY(teacher);
cout << "teacher name: " << teacher.getName() << endl;
cout << "teacher age: " << teacher.getAge() << endl;
system("pause");
}
輸出結果:
MyTeacher 構造函數 地址:00C2FD60
teacher name: 張三
teacher age: 18
setFunc teacher name: yuehan
setFunc teacher age: 31
teacher name: yuehan
teacher age: 31
最後發現替換成功
四 內存空間的分配
每頁內存空間
-
.text段
可執行代碼、只讀變量,全局靜態變量 -
.data段
已初始化且初值非0的全局變量和靜態局部變量 -
.bss段
未初始化或初值爲0的全局變量和靜態局部變量 -
堆(heap)空間:
動態分配的內存(malloc 等api 分配在堆空間, c++中的new)
堆用於存放進程運行時動態分配的內存段,可動態擴張或縮減。堆中內容是匿名的,不能按名字直接訪問,只能通過指針間接訪問。 -
棧(stack)空間:
局部變量、函數參數、返回地址等(系統自動分配的臨時內存)Linux有專門的寄存器管理棧內存(效率高)
五 引用
1 引用與引用別名
-
教課書上說的是引用是原變量的一個別名.
n 相當於m 的別名(綽號),對n 的任何操作就是對m 的操作。例如有個人叫是J,綽號是“馬爸爸”。說“馬爸爸”怎麼怎麼的,其實就是在說J。所以n 既不是m 的拷貝,也不是指向m 的指針,其實n就是m 它自己。
-
c++中的引用 (就是再堆中分配空間)
- 單純給變量取別名沒有任何意義,作爲函數參數傳遞,能保證參數傳遞過程中不產生副本
- 引用可以直接操作變量,指針要通過取值(*p),間接操作變量,指針的可讀性差
-
java的引用和句柄
內存分配在堆空間, 引用和句柄分配在棧空間 -
java中的引用(強引用,弱引用,軟引用,虛引用)
2 指針和引用的區別
-
指針是一個實體,而引用僅是個別名;
-
引用使用時無需解引用(*),指針需要解引用;
-
引用只能在定義時被初始化一次,之後不可變;指針可變;
引用“從一而終”
-
引用沒有 const,指針有 const,const 的指針不可變;
-
引用不能爲空,指針可以爲空;
-
“sizeof 引用”得到的是所指向的變量(對象)的大小,而“sizeof 指針”得到的是指針本身(所指向的變量或對象的地址)的大小;
常用的引用方式(指針的引用—代替二級指針)