1.構造函數:(與類名相同,並且可以發生重載)
- 默認構造函數(無參):
- 有參構造函數(有參):
- 拷貝構造函數(參數爲另一個對象):
2.析構函數:
注意:1.構造函數和析構函數必須寫在public權限下面。
2.有默認值的構造函數不能再去創建無參的同名的構造函數
3.構造函數的調用方式:
1. 括號法調用
括號法調用
Person p1(1); //有參
p1.m_Age = 10;
Person p2(p1); //拷貝
cout << "p2的年齡" << p2.m_Age << endl;
Person p3; //默認構造函數 不要加() Person p3(); //編譯器認爲這行是函數的聲明
//括號法調用就是調用有參構造函數和拷貝構造函數。如果想調用默認構造函數,什麼都不要加。
2.顯示法調用
Person p4 = Person(100);
Person p5 = Person(p4);
Person(100); //叫匿名對象 ,匿名對象特點,如果編譯器發現了對象是匿名的,那麼在這行代碼結束後就釋放這個對象,不用對象去接直接生成一個對象就是所謂的匿名對象。
不能用拷貝構造函數 初始化匿名對象
Person p6 = Person(p5); //如果寫成左值,編譯器認爲你寫成 Person p5; 對象的聲明,如果寫成右值,那麼可以
3.隱式類型轉換:
Person p7 = 100; //相當於調用了 Person p7 = Person(100) ,隱式類型轉換
Person p8 = p7; // 相當於 Person p8 = Person(p7);
上面那種方式我覺得這種隱式類型轉換隻適用於屬性只有一個這種情況。
並且g++ 編譯器不允許person p7 = 100; 這種寫法 。但是在vs環境中是可以的。第二種方式在g++ 和vs 兩種環境都可以。
4.構造函數的調用規則:
1)當我們提供了有參構造函數,那麼系統就不會在給我們提供默認構造函數了,但是 系統還會提供默認拷貝構造函數 , 進行簡單的值拷貝;
2)當我們提供了 拷貝構造,那麼系統就不會提供其他構造了;
3)簡單的值拷貝,意思就是就是直接賦值,但是並不會考慮到內存相關的管理。
5.深拷貝和淺拷貝就是關於內存管理以及拷貝構造函數的相關的一些注意點:
深拷貝和淺拷貝主要原因是在於系統提供的默認拷貝函數是隻提供了簡單的值拷貝,並且如果我們的類裏面 操作了一些我們申請的內存,就會出現深拷貝和淺拷貝的問題,形象的代碼用C語言代碼來示例更好:
class person
{
public:
person()
{
}
person(char *name1,int age)
{
this->name = (char *)malloc(strlen(name1)+1);
strcpy(this->name,name1);
this->age = age;
}
~person()
{
if(this->name != NULL)
{
free(this->name);
this->name = NULL;
}
}
int age;
char *name;
};
int main(void)
{
person p1("duqian",10);
person p2(p1);
return 0;
}
上述代碼會出錯,我們需要自己寫一個拷貝構造函數來替代掉默認的拷貝構造函數:
class person
{
public:
person()
{
}
person(char *name1,int age)
{
this->name = (char *)malloc(strlen(name1)+1);
strcpy(this->name,name1);
this->age = age;
}
person(person &p)
{
this->age = p.age;
this->name = (char *)malloc(sizeof(p.name)+1);
strcpy(this->name,p.name);
}
~person()
{
if(this->name != NULL)
{
free(this->name);
this->name = NULL;
}
}
int age;
char *name;
};
int main(void)
{
person p1("duqian",10);
person p2(p1);
return 0;
}
上述就是深拷貝和淺拷貝。
6.explicit 關鍵字:
如果類的構造函數裏面,提供了一個一個參數的構造函數(包括了默認參數的情況),那麼是可以使用隱式類型轉換的。加上explicit 關鍵字,則不支持隱式類型轉換。
class person
{
public:
person()
{
}
//在這個構造函數前面加explicit ,則這個類就不支持隱式類型轉換了.
person(int a)
{
this->age = a;
}
person(int a,int b)
{
this->age = a;
this->num = b;
}
person (person &p)
{
this->age = p.age;
this->num = p.num;
}
void func()
{
cout <<this->age<<endl;
}
int age;
int num;
};
int main(void)
{
//g++支持這樣的方式
person p1(12,13);
p1 = 100;
// g++ 編譯器不支持,vs編譯器支持 person p1 = 100;
p1.func();
return 0;
}
7.初始化列表:
//主要是用來初始化數據的
//構造函數後面 + : 屬性(參數), 屬性(參數)...
person(int a,int b):age(a),num(b)
{
}