❶ java中的構造方法是個什麼意思,為什麼一定通過它來為成員賦初值,直接賦不行嗎
構造方法就是上戶口,上戶口派出所必須要求你出示必要條件,男人還是女人,出生日期,父母姓名。這些必須是上戶口的時候必須具備的,否則上個空頭戶口那就亂套了。勢必是活不見人死不見屍。先開個空頭戶口,在讓你寫名字,這就意味著,你這個戶口可以是張三,還能是李四,到時候戶口起不到作用了。
❷ java中為什麼要有構造方法
一個對象被創建出來時,經常要先做一些事這個對象才能正常使用,也可以說是准備工作,比如給這個對象賦些初始值,或者先運行一些別的方法。
把那些在創建時要做的事寫在構造方法里,每次創建就會被執行一遍。
就你描述的情況,默認構造方法其實就什麼都沒做啊,但是會有對象創建的時候就要賦值一些成員變數的情況,這種就要自定義構造方法,重載啊。可能你會說為什麼非得要構造的時候就賦值呢,不能對象創建出來,set成員變數就得了。原因:1是麻煩。2是會有很多人創建了對象,忘記了set某些成員變數,然後直接去調用對象的別的方法,這時可能就會由於對象未賦值而拋出異常。
❸ 在構造函數當中,給變數賦值意味著什麼,是不是意味直接給變數賦值呢
當然不是,構造函數是實例化的時候用的,在構造函數中給變數復制意味著當你使用這個構造函數實例化一個對象的時候才給變數賦值
因為根據函數重載一個類可以有很多不同的構造函數,當你選擇不同的構造函數實例化對象的時候給變數可以賦不同的值
❹ 在構造函數中對成員變數進行初始化的好處
這個當然了。。。
類的構造函數中初始化就相當於你獲取這個對象的時候成員變數就初始化好了,變數定義時要初始化樓主總知道為什麼吧?
這樣的話就不用顯示的初始化成員變數了。
❺ 構造方法有什麼作用
作用就是對類進行初始化。
如果你沒有定議任何構造方法的形式,程式會為你取一個不帶任何參數的構造函數,那麼你產生類的對像時只能用不帶參數的方法,如:class a {}//沒有任何構造函數,class b{ a c = new a();}//a()不能帶任何參數。
❻ 構造函數中對參數的賦值起到什麼作用比方說,void g(int i=10){}
你這個構造函數有錯誤的吧,構造函數沒有函數類型
應該寫成g(int i = 10){}
構造函數中的參數一般是用這個值進行初始化
只是有一點要注意,在C++中,構造函數的默認值參數必須出現在最後:
g(int i, int j, int k = 10){} //正確
g(int i, int j = 10, int k){}//不正確
g(int i, int j = 5, int k = 10){}//正確
❼ 對類的成員變數使用private許可權,在通過構造方法對他進行賦值和直接給他public許可權直接賦值有什麼區別
數據的封裝性啊,難道你不覺得就算可以在外面訪問private也要麻煩一些了么?對了,這就是面向對象。它的好處就是增加間接層,提高數據訪問的集中和安全性。比如,你的private int m_name;我現在要是通過public setname(string name)來為其賦值的話,我現在可以在setname中過濾一下不合法的值了,但是你試試把訪問權改為public,那就會麻煩很多,而且容易出錯。至於構造函數,那個只能在實例化對象時被自動或顯示調用,其他時候是不能手動調用的,所以不存在你說的那些問題。另外,class成員是可以直接訪問private 值域的
❽ Java中為什麼要用構造方法初始話成員變數,直接像int a=5這樣聲明不就可以了嗎
聲明時初始化,當然是最好的了。但萬一有人沒有在聲明時初始化呢?這就用構造方法初始化,即經過構造方法,java保證所有成員變數都是初始化過的。
1、類的成員變數都是由構造方法初始化的。就像某個類中有private int a = 5;這個實際上的初始化是在構造方法中完成的。
2、另外重要的一點,當類成員變數沒有被初始化時,(private int a;)構造方法會用預設值將其初始化,int的初始為0 引用類型初始為null等。
❾ 在c語言中給變數賦初值有什麼作用
語法上的初始化是指對象定義時,對應的分配空間之後對於值的操作。c語言中,靜態和全局變數默認置0,有初始化列表的復制初始化列表的值到空間(如有不足,剩餘部分置0),局部自動變數可以不初始化(調試器參與時可能被隱式地初始化為其它的值("debug
magic
number"),例如默認情況下microsoft
c/c++
debugger會把棧中未初始化的位元組置為0xcc)。
賦初值一般而言是指邏輯意義上的初始化。在c語言中,由於初始化的語法是「=」後加初值,所以「賦初值」基本上就是指語法上的初始化。不過隨著語言的發展,「賦初值」的意義發生了擴大。對有構造語義但又允許不初始化而不產生編譯錯誤的程序設計語言而言,兩者有些微妙的差別。例如c++的構造函數中,用若干個成員名和括弧括起來的初始化值構成的初始化列表是語法上的初始化(也可能是邏輯意義上的初始化,如果沒有被構造函數體內的值覆蓋),而構造函數體中對成員的賦值語句是邏輯上的初始化但不是語法上的初始化。
冰的悸動
錯誤:
1.「程序開始時進行初始化」的說法僅僅適用於靜態或全局變數,而不適於局部自動變數。局部自動變數在函數調用時才能被初始化。
2.「但是根據編譯器的不同有些編譯器會自動賦初值0或其他」——這在iso/iec
c語言標准中不是由實現定義的行為,如果一個編譯器符合標准,那麼行為就是明確的,即視此初始化的對象是否為全局對象來判斷隱式初始化置0還是不進行初始化——從下面的函數定義來看這里應該var2是全局變數,會被置0。非標准編譯器則另當別論(但是我還沒見過會在這點上沒事找茬的)。
❿ C/C++ 通過初始化列表和構造函數內賦值初始化成員變數的區別
一般我們進行成員變數初始化用兩種方法
第一種是通過在構造函數內賦值
class Point
{
public:
Point(){ _x = 0; _y = 0;};
Point( int x, int y ){ _x = 0; _y = 0; }
private:
int _x, _y;
};
第二種是使用初始化列表
class Point
{
public:
Point():_x(0),_y(0){};
Point( int x, int y ):_x(x),_y(y){}
private:
int _x, _y;
};
這兩種用法是有區別的
一、在有些情況下,必須使用初始化列表。特別是const和引用數據成員被初始化時。
class Point
{
// 這個類的定義就要求使用初始化成員列表,因為const成員只能被初始化,不能被賦值
public:
Point():_x(0),_y(0){};
Point( int x, int y ):_x(x),_y(y){}
//Point(){ _x = 0; _y = 0;}
//Point( int x, int y ){ _x = 0; _y = 0; }
private:
const int _x, _y;
};
二、是從效率方面來說的,對於內置類型或復合類型,差異不會太大,但對於非內置數據類型,差異還是很明顯的
如我們再給Point類添加一個新的string類型的成員變數
class Point
{
const int _x, _y;
string _name;
};
構造函數內賦值進行初始化
Point( int x, int y, string name ){ _x = 0; _y = 0; _name = name; }
_name = name 這個表達式會調用string類的預設構造函數一次,再調用Operator=函數進行賦值一次。所以需調用兩次函數:一次構造,一次賦值
用初始化列表進行初始化
Point( int x, int y, string name ):_x(x),_y(y), _name(name){}
_name會通過拷貝構造函數僅以一個函數調用的代碼完成初始化
即使是一個很簡單的string類型,不必要的函數調用也會造成很高的代價。隨著類越來越大,越來越復雜,它們的構造函數也越來越大而復雜,那麼對象創建的代價也越來越高,所以一般情況下建議使用初始化列表進行初始化,不但可以滿足const和引用成員的初始化要求,還可以避免低效的初始化數據成員。
詳細出處參考:http://www.itqun.net/content-detail/105800_2.html
————————————————————————————————————————————————————————
C++構造函數中初始化成員__參數列表初始化成員(必須用原因:對象成員的初始化,const修飾的成員的初始化,引用成員的初始化,子類調用父類的構造函數初始化父類成員)__參數列表在構造函數執行之前執行,參數列表中執行的是初始化(所有的成員,無論是否出現在參數列表中,都會有初始化),參數列表的執行順序與類中成員的聲明順序,與類的繼承順序相一致__構造函數中執行的一般是賦值_多重繼承,虛繼承構造函數的參數初始化列表的區別
類對象的構造順序是這樣的:
1.分配內存,調用構造函數時,隱式/顯示的初始化各數據成員;
2.進入構造函數後在構造函數中執行一般賦值與計算。
使用初始化列表有兩個原因:
原因1.必須這樣做:
《C++ Primer》中提到在以下三種情況下需要使用初始化成員列表:
一、需要初始化的數據成員是對象的情況(這里包含了繼承情況下,通過顯示調用父類的構造函數對父類數據成員進行初始化);
二、需要初始化const修飾的類成員;
三、需要初始化引用成員數據;
即:
例一、數據成員是對象,切對象只有含參數的構造函數;
如果我們有一個類成員,它本身是一個類或者是一個結構,而且這個成員它只有一個帶參數的構造函數,而沒有默認構造函數,這時要對這個類成員進行初始化,就必須調用這個類成員的帶參數的構造函數,如果沒有初始化列表,那麼他將無法完成第一步,就會報錯。
class Test
{
public:
Test(int x,int y,int z);
private:
int a;
int b;
int c;
};
class MyTest
{
public:
MyTest():test(1,2,3){} //初始化,初始化列表在構造函數執行前執行(這個可以測試,對同一個變數在初始化列表和構造函數中分別初始化,首先執行參數列表,後在函數體內賦值,後者會覆蓋前者)。
private:
Test test; //聲明
};
因為Test有了顯示的帶參數的構造函數,那麼他是無法依靠編譯器生成無參構造函數的,所以沒有三個int型數據,就無法創建Test的對象。
Test類對象是MyTest的成員,想要初始化這個對象test,那就只能用成員初始化列表,沒有其他辦法將參數傳遞給Test類構造函數。
例二、對象引用或者cosnt修飾的數據成員
另一種情況是這樣的:當類成員中含有一個const對象時,或者是一個引用時,他們也必須要通過成員初始化列表進行初始化,因為這兩種對象要在聲明後馬上初始化,而在構造函數中,做的是對他們的賦值,這樣是不被允許的。
即:
class Test
{
priate:
const int a; //const成員聲明
public:
Test():a(10){} //初始化
};
或
class Test
{
private:
int &a; //聲明
public:
Test(int a):a(a){} //初始化
}
例三、子類初始化父類的私有成員,需要在(並且也只能在)參數初始化列表中顯示調用父類的構造函數,如下:
class Test
{
private:
int a;
int b;
int c;
public:
Test(int a,int b,int c)
{
this->a = a;
this->b = b;
this->c = c;
}
int getA(){return a;}
int getB(){return b;}
int getC(){return c;}
};class MyTest:public Test
{
private:
int d;
public:
MyTest(int a,int b,int c,int d):Test(a,b,c)
//MyTest(int a,int b,int c,int d)
{
//Test(a,b,c); //構造函數只能在初始化列表中被顯示調用,不能在構造函數內部被顯示調用
this->d = d;
}
int getD(){return d;}
}; int main(int argc,char *argv[])
{
MyTest mytest(1,2,3,4);
printf("a=%d,b=%d,c=%d,d=%d\n",
mytest.getA(),mytest.getB(),mytest.getC(),mytest.getD());
return 0;
}
多重繼承,虛繼承構造函數的參數初始化列表的區別:
代碼如下:
注意多重繼承子類的構造函數#include <stdio.h>
class CTop
{
private:
int a;
public:
int getA()
{
return a;
}
CTop(int a)
{
this->a = a;
}
};
class CLeft:public CTop
{
private:
int b;
public:
int getL()
{
return b;
}
CLeft(int a,int b):CTop(a)
{
this->b = b;
}
};
class CRight:public CTop
{
private:
int c;
public:
int getR()
{
return c;
}
CRight(int a,int c):CTop(a)
{
this->c = c;
}
};
class Test:public CLeft,public CRight
{
private:
int d;
public:
int getT()
{
return d;
}
Test(int a,int b,int c,int d):CLeft(a,b),CRight(a,c)
{
this->d = d;
}
};
int main(int argc,char *argv[])
{
Test obj(1,2,3,4);
printf("obj.a=%d,obj.b=%d,obj.c=%d,obj.d=%d\n",
obj.CLeft::getA(),obj.getL(),obj.getR(),obj.getT()); //getA有歧義,要用類名來做區分。
return 0;
} 注意虛繼承子類的構造函數#include <stdio.h>
class CTop
{
private:
int a;
public:
int getA()
{
return a;
}
CTop(int a)
{
this->a = a;
}
};
class CLeft:virtual public CTop{
private:
int b;
public:
int getL()
{
return b;
}
CLeft(int a,int b):CTop(a)
{
this->b = b;
}
};
class CRight:virtual public CTop
{
private:
int c;
public:
int getR()
{
return c;
}
CRight(int a,int c):CTop(a)
{
this->c = c;
}
};
class Test:public CLeft,public CRight
{
private:
int d;
public:
int getT()
{
return d;
}
Test(int a,int b,int c,int d):CLeft(a,b),CRight(a,c),CTop(a)
{
this->d = d;
}
};
int main(int argc,char *argv[])
{
Test obj(1,2,3,4);
printf("obj.a=%d,obj.b=%d,obj.c=%d,obj.d=%d\n",
obj.getA(),obj.getL(),obj.getR(),obj.getT()); //因為採用虛基類,虛繼承機制保證了a只有一份,所以不存在歧義。
return 0;
}
原因2.效率要求這樣做:
類對象的構造順序顯示,進入構造函數體後,進行的是計算,是對成員變數的賦值操作,顯然,賦值和初始化是不同的,這樣就體現出了效率差異,如果不用成員初始化類表,那麼類對自己的類成員分別進行的是一次隱式的默認構造函數的調用,和一次賦值操作符的調用,如果是類對象,這樣做效率就得不到保障。
注意:構造函數需要初始化的數據成員,不論是否顯示的出現在構造函數的成員初始化列表中,都會在該處完成初始化,並且初始化的順序和其在類中聲明時的順序是一致的,與列表的先後順序無關,所以要特別注意,保證兩者順序一致才能真正保證其效率和准確性。
為了說明清楚,假設有這樣一個類:
class foo{
private :
int a, b;
};
1、foo(){}和foo(int i = 0){}都被認為是默認構造函數,因為後者是默認參數。兩者不能同時出現。
2、構造函數列表的初始化方式不是按照列表的的順序,而是按照變數聲明的順序。比如foo裡面,a在b之前,那麼會先構造a再構造b。所以無論foo():a(b + 1), b(2){}還是foo():b(2),a(b+1){}都不會讓a得到期望的值。
3、構造函數列表能夠對const成員初始化。比如foo裡面有一個int const c;則foo(int x) : c(x){}可以讓c值賦成x。
不過需要注意的是,c必須在每個構造函數(如果有多個)都有值。
4、在繼承裡面,只有初始化列表可以構造父類的private成員(通過顯示調用父類的構造函數)。比如說:
class child : public foo
{
};
foo裡面的構造函數是這樣寫的:
foo (int x)
{
a = x;
}.
而在child裡面寫child(int x){ foo(x); }是通過不了編譯的。
只有把子類構造函數寫作child (int x) : foo(x){}才可以。
——————————————————————————————————————————————————————————————————
關於復合類型:
C++中,什麼是復合類型?
剛開始,還以為自定義的類是復合類型。查了C++ primer才知道復合類型不是類。
在C++中類型大致可以分為三種
一、內置類型
如int, char, float, unsigned等。內置類型是最基本的類型。
二、復合類型
復合類型:使用其它類型定義的類型。有三種復合類型:引用,指針,數組。
三、類類型
就是類。比如string以及自己定義的類。
數組、結 構和指針式c++的3種復合類型。
數組,可以在一個數據對象中存儲多個同種類型的值。通過使用索引或下標,可以訪問數組中的各個元素。
結構,可以將多個不同類型的值存儲在同一個數據對象中,可以使用成員關系操作符(.)來訪問其中的成員。使用結構的第一步是創建結構模板,它定義了結構存儲了哪些成員。模板的名稱將成為新類型的標識符,然後就可以聲明這種類型的結構變數。
共用體,可以存儲一個值,但是這個值可以是不同的類型,成員名指出了使用的模式。
指針,是被設計用來存儲地址的變數的。我們說,指針指向它存儲的地址。指針聲明指出了指針指向的對象的類型。對指針應用解除引用操作符,將得到指針指向的位置中的值。
字元串,是以空字元為結尾的一系列字元。字元串可用引號括起來的字元串常量表示,其中隱式包含了結構的空字元。可以將字元串存儲在char數組中,可以用被初始化為指向字元串的 char指針表示字元串。函數strlen()返回字元串的長度,其中不包括空字元。函數strcpy()將字元串從一個位置復制到另一個位置。在使用這些函數時,應包含頭文件cstring或string.h.
頭文件string支持 的C++string類提供了另一種對用戶更為友好的字元串處理方法。具體地說,string對象將根據要存儲的字元串自動調整其大小,用戶可以使用賦值操作符來復制字元串。
New操作符允許在程序運行時為數據對象請求內存。該操作符返回其內存的地址,可以將這個地址賦給一個指針,程序將只能使用該指針來訪問內存。如果數據對象是簡單變數,則可以使用解除引用操作符(*)來獲得其值;如果數據對象是數組,則可以像使用數組名那樣來使用指針來訪問元素;如果數據對象是結構,則可以用指針解除引用操作符(->) 來訪問其成員。
指針和數 組緊密相關。如果ar是數組名,則表達式ar[i]被解釋為*(ar+i),其中數組名被解釋為數組第一個元素的地址。這樣,數組名的作用和指針相同。反過來,可以使用數組表示法,通過指針名來訪問new分配的數組中的元素。
操作符new和delete 允許顯式控制何時給數據對象分配內存,何時將內存歸給內存池。自動變數是在函數中聲明的變數,而靜態變數時在函數外部或者使用關鍵字static聲明的變數,這兩種變數都不太靈活。自動變數在程序執行到其所屬的代碼塊(通常是函數定義)時產生,在離開該代碼塊時終止。靜態變數在整個程序周期內部都存在。
轉載自:http://blog.csdn.net/arcsinsin/article/details/39379811