struct 和 class的區別
C++中可以通過使用struct、class定義一個類,本質上他們沒有任何的區別,唯一的區別就是struct的默認成員權限是public,class默認成員權限是private
構造函數
構造函數(也叫構造器),在對象創建的時候自動調動,一般用於完成對象的初始化工作
特點:
函數名與類名同名,無返回值(void 也不寫),可以有參數,可以重載,可以有多個構造函數
一旦定義了一個構造函數,就必須使用其中一個自定義的構造函數來初始化
Example
class Person {
int m_age;
Person() {}
Person(int age):m_age(age){}
void display(){
cout << this->m_age << endl;
}
};
Person g_p1; //Person()
Person g_p2(); //這是一個函數聲明,函數名叫g_p2,返回類型Person,無參
Person g_p3(20); //Person(int)
int main(){
Person p1; //Person()
Person p2(); //這是一個函數聲明,函數名叫g_p2,返回類型Person,無參
Person p3(20); //Person(int)
Person *p4 = new Person; //Person()
Person *p5 = new Person(); //Person()
Person *p6 = new Person(20); //Person(int)
return 0;
}
注意
- 通過malloc分配的對象不會調用構造函數,並且需要注意的是編譯器並不一定會為每一個類生成空的無參構造函數,是否生成構造函數取決於是否需要做些額外的事情(內存操作,函數調用),比如:
- 成員變量在聲明的同事進行了初始化
- 有定義虛函數
- 虛繼承了其他類
- 包含了對象類型的成員,且這個成員有構造函數(編譯器生成或者自定義)
- 父類有構造函數(編譯器生成或者自定義)
默認情況下成員變量的初始化
Person g_p1; //全局區,成員變量初始化為0
int main(){
Person p1; //棧區不會被初始化
Person *p2 = new Person; //成員變量不會被初始化
Person *p3 = new Person(); //成員變量初始化為0
Person *p4 = new Person[3]; //成員變量不會被初始化
Person *p5 = new Person[3](); //3個Person對象的成員變量都初始化為0
Person *p6 = new Person(){}; //3個Person對象的成員變量都初始化為0
cout << "g_p1" << g_p1.getAge() << endl;
cout << "p1" << g_p1.getAge() << endl;
cout << "p2" << g_p2->getAge() << endl;
cout << "p3" << g_p3->getAge() << endl;
cout << "p4" << g_p4->getAge() << endl;
cout << "p5" << g_p5->getAge() << endl;
cout << "p6" << g_p6->getAge() << endl;
return 0;
}
如果自定義了構造函數,除了全局區,其他內存空間的成員變量默認都不會被初始化,需要開發人員手動初始化
Person() {
memset(this,0,sizeof(Person));//初始化全部成員變量為0
}
析構函數
析構函數(析構器),在對象銷毀的時候自動調用,一般用於完成對象的清理工作
特點:
函數名以~開頭,與類同名,無返回值(void也不寫),無參,不可以重載,有且只有一個析構函數
注意
通過malloc分配的對象調用free的時候不會調用析構函數
構造函數、析構函數要聲明為public,才能被外界正常使用,析構函數通常用來處理對象內部申請的堆空間,在對象銷毀的時候由對象內部自己回收。
class Car
{
private:
int m_price;
public:
Car() {};
~Car() {};
};
class Person {
Car *m_car;
Person() {
m_car = new Car();
}
~Person() {
if(m_car == nullptr) return;
delete m_car;
m_car = nullptr;
}
};