C++中的幾種特殊成員函數(shù)
構(gòu)造函數(shù)
C++在編譯器會(huì)給我們默認(rèn)創(chuàng)建一個(gè)缺省的構(gòu)造方法: 如下代碼:
class Father {
public:
string name = "father";
int age = 45;
void print() {
cout << "name:" << name << " age:" << age << endl;
}
};
class Son :public Father {
public:
string sex = "male";
};
void extendsTest::mainTest()
{
Son son;
son.print();
};
運(yùn)行結(jié)果:name:father age:45
可以看到雖然我們沒(méi)有明確聲明構(gòu)造方法,但是依然可以調(diào)用無(wú)參構(gòu)造方法。這就是因?yàn)?編譯器自動(dòng)給我們創(chuàng)建了一個(gè)無(wú)參構(gòu)造方法 、
如果類定義了自己的構(gòu)造方法后(包括無(wú)參和有殘),編譯器就不會(huì)給我們創(chuàng)建了 ,看下面代碼:
class Father {
public:
Father() {
cout << "Father:" << name << endl;
}
string name = "father";
int age = 45;
void print() {
cout << "name:" << name << " age:" << age << endl;
}
};
class Son :public Father {
public:
Son(){
cout << "Son:" << name << endl;
}
string sex = "male";
};
void extendsTest::mainTest()
{
Son son;
son.print();
};
打印結(jié)果:
Father:father
Son:father
name:father age:45
從上面代碼也可以看出C++編譯器會(huì)默認(rèn)優(yōu)先調(diào)用父類的構(gòu)造方法,再調(diào)用子類的構(gòu)造方法,
這點(diǎn)和java中是有區(qū)別的,java會(huì)從子類開(kāi)始依次調(diào)用父類的構(gòu)造方法,然后回溯子類的構(gòu)造方法
所以為了保證對(duì)象的順利創(chuàng)建,需要保證父類的構(gòu)造方法是有效的。 如下代碼:
class Father {
public:
Father(string _name):name(_name){
cout << "Father:" << name << endl;
}
string name = "father";
int age = 45;
};
此時(shí)父類中創(chuàng)建了一個(gè)有參構(gòu)造方法,前面說(shuō)過(guò),此時(shí)編譯器不會(huì)創(chuàng)建默認(rèn)的無(wú)參構(gòu)造方法,則需要保證在其子類中有初始化父類的操作:即調(diào)用父類有參構(gòu)造方法。 如下代碼:
class Son :public Father {
public:
Son(string name):Father(name) {
cout << "Son:" << name << endl;
}
string sex = "male";
};
void extendsTest::mainTest()
{
Son son1("myName");
};
結(jié)果:
Father:myName
Son:myName
析構(gòu)函數(shù)
析構(gòu)函數(shù)用來(lái)釋放當(dāng)前對(duì)象使用到的內(nèi)存空間,當(dāng)對(duì)象跳出其作用域范圍后就會(huì)執(zhí)行析構(gòu)函數(shù)( 除非是有智能指針出現(xiàn)循環(huán)引用的情況,無(wú)法釋放,導(dǎo)致泄露 )。 C++中析構(gòu)函數(shù)和構(gòu)造函數(shù)相反,會(huì) 優(yōu)先調(diào)用子類的析構(gòu)函數(shù)再調(diào)用父類的析構(gòu)函數(shù) 。 如下代碼:
class Father {
public:
~Father() {
cout << "~Father"<< endl;
}
string name = "father";
int age = 45;
};
class Son :public Father {
public:
~Son() {
cout << "~Son" << endl;
}
string sex = "male";
};
void extendsTest::mainTest()
{
Son son;
};
運(yùn)行結(jié)果:
~Son
~Father
拷貝構(gòu)造
C++中拷貝構(gòu)造函數(shù)格式:
- 格式1 :帶const參數(shù) Complex(const Complex& c) { … } 表示以常量對(duì)象作為參數(shù)
- 格式2 :不帶const參數(shù) Complex(Complex& c) { … } 表示以非常量作為參數(shù)進(jìn)行拷貝 如下代碼:
class Complex {
public:
double real, imag;
Complex(double _real, double _imag):
real(_real),imag(_imag)
{
cout << "real:" << real << " imag:" << imag << endl;
}
void print() {
cout << "real:" << real << " imag:" << imag << endl;
}
Complex(Complex& c) {
real = c.real+1; imag = c.imag+1;
}
};
void extendsTest::mainTest()
{
Complex c1(1.0, 2.0);
Complex c2(c1);
c2.print();
};
打印結(jié)果:
real:1 imag:2
real:2 imag:3
拷貝構(gòu)造函數(shù)和構(gòu)造方法類似, C++編譯器會(huì)給我們提供默認(rèn)的拷貝構(gòu)造函數(shù) 。 將上面代碼的拷貝構(gòu)造函數(shù)刪除后:
class Complex {
public:
double real, imag;
Complex(double _real, double _imag):
real(_real),imag(_imag)
{
cout << "real:" << real << " imag:" << imag << endl;
}
void print() {
cout << "real:" << real << " imag:" << imag << endl;
}
};
void extendsTest::mainTest()
{
Complex c1(1.0, 2.0);
Complex c2(c1);
c2.print();
};
依然可以執(zhí)行拷貝構(gòu)造,此時(shí)c2使用了默認(rèn)拷貝構(gòu)造函數(shù)進(jìn)行賦值。
拷貝構(gòu)造的幾種調(diào)用形式:
-
1.當(dāng)用一個(gè)對(duì)象去初始化同類的另一個(gè)對(duì)象時(shí)
Complex c2(c1); Complex c2 = c1;
這兩天語(yǔ)句是等價(jià)的。但是要 注意此時(shí)Complex c2 = c1是一個(gè)初始化語(yǔ)句,并非一個(gè)賦值語(yǔ)句。賦值語(yǔ)句是一個(gè)已經(jīng)初始化后的變量 。 如下:
Complex c1, c2; c1 = c2 ; c1=c2;
賦值語(yǔ)句不會(huì)觸發(fā)拷貝構(gòu)造 。
-
2.當(dāng)對(duì)象作為一個(gè)函數(shù)形參時(shí),此時(shí)也會(huì)觸發(fā)對(duì)象的拷貝構(gòu)造
class Complex { public: double real, imag; Complex(double _real, double _imag): real(_real),imag(_imag) { cout << "real:" << real << " imag:" << imag << endl; } Complex(Complex& c) { real = c.real+1; imag = c.imag+1; cout << "complex copy" << endl; } }; void func(Complex c) { cout << "real:" << c.real << " imag:" << c.imag << endl; } void extendsTest::mainTest() { Complex c(1.0,2.0); func(c); }; 運(yùn)行結(jié)果: real:1 imag:2 complex copy real:2 imag:3
可以看到運(yùn)行結(jié)果觸發(fā)了Complex的拷貝構(gòu)造 以對(duì)象作為函數(shù)的形參,在函數(shù)被調(diào)用時(shí),生成的形參要用復(fù)制構(gòu)造函數(shù)初始化,這會(huì)帶來(lái)時(shí)間上的開(kāi)銷。 如果用對(duì)象的引用而不是對(duì)象作為形參,就沒(méi)有這個(gè)問(wèn)題了 。
void func(Complex& c) { cout << "real:" << c.real << " imag:" << c.imag << endl; }
但是以引用作為形參有一定的風(fēng)險(xiǎn),因?yàn)檫@種情況下如果形參的值發(fā)生改變,實(shí)參的值也會(huì)跟著改變。 最好的方法就是將函數(shù)形參聲明為const類型的引用 。
void func(const Complex& c) { cout << "real:" << c.real << " imag:" << c.imag << endl; }
-
3.對(duì)象作為函數(shù)返回值返回時(shí),也會(huì)觸發(fā)拷貝構(gòu)造。
Complex func() { Complex c(1.0, 2.0); return c; } void extendsTest::mainTest() { cout << func().real << endl; }; 結(jié)果: real:1 imag:2 complex copy 2
可以看到此時(shí)func函數(shù)中的return c處會(huì)觸發(fā)一次拷貝構(gòu)造,并將拷貝后的對(duì)象返回。 這點(diǎn)通過(guò)函數(shù)hack過(guò)程也可以看出來(lái):此處call方法執(zhí)行的是拷貝構(gòu)造方法
-
JAVA
+關(guān)注
關(guān)注
19文章
2966瀏覽量
104702 -
C++
+關(guān)注
關(guān)注
22文章
2108瀏覽量
73618 -
面向?qū)ο缶幊?/span>
+關(guān)注
關(guān)注
0文章
22瀏覽量
1811
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論