構造函式

構造函式

構造函式 ,是一種特殊的方法。主要用來在創建對象時初始化對象, 即為對象成員變數賦初始值,總與new運算符一起使用在創建對象的語句中。特別的一個類可以有多個構造函式 ,可根據其參數個數的不同或參數類型的不同來區分它們 即構造函式的重載

基本介紹

  • 中文名:構造函式
  • 外文名:constructor
  • 作用:為對象成員變數賦初始值
  • 語句:new運算符一起使用
主要特點,套用,其他特點,語法,記憶體機制,語言細節,Java,Visual Basic .NET,C#,C++,Ruby,

主要特點

1.構造函式的命名必須和類名完全相同。在java中普通函式可以和構造函式同名,但是必須帶有返回值;
2.構造函式的功能主要用於在類的對象創建時定義初始化的狀態。它沒有返回值,也不能用void來修飾。這就保證了它不僅什麼也不用自動返回,而且根本不能有任何選擇。而其他方法都有返回值,即使是void返回值。儘管方法體本身不會自動返回什麼,但仍然可以讓它返回一些東西,而這些東西可能是不安全的;
3.構造函式不能被直接調用,必須通過new運算符在創建對象時才會自動調用;而一般的方法是在程式執行到它的時候被調用的;
4.當定義一個類的時候,通常情況下都會顯示該類的構造函式,並在函式中指定初始化的工作也可省略,不過Java編譯器會提供一個默認的構造函式.此默認構造函式是不帶參數的。而一般的方法不存在這一特點;
5.構造函式有回滾的效果,構造函式拋出異常時,構造的是一個不完整對象,會回滾,將此不完整對象的成員釋放(c++)
6.當一個類只定義了私有的構造函式,將無法通過new關鍵字來創建其對象,當一個類沒有定義任何構造函式,C#編譯器會為其自動生成一個默認的無參的構造函式。
7.在Python中構造函式必須通過重寫__init__方法實現

套用

C++構造函式
C++語言為類提供的構造函式可自動完成對象的初始化任務,全局對象和靜態對象的構造函式在main()函式執行之前就被調用,局部靜態對象的構造函式是當程式第一次執行到相應語句時才被調用。然而給出一個外部對象的引用性聲明時,並不調用相應的構造函式,因為這個外部對象只是引用在其他地方聲明的對象,並沒有真正地創建一個對象。
C++的構造函式定義格式為:
class <類名>
{
public:
<類名>(參數表);
//...(還可以聲明其它成員函式)
};
<類名>::<函式名>(參數表)
{
}
如以下定義是合法的:
class T
{
public:
T(int a=0){ i=a; }//構造函式允許直接寫在類定義內,也允許有參數表。
private:
int i;
};
如果一個類中沒有定義任何的構造函式,那么編譯器只有在以下三種情況,才會提供默認的構造函式:
1、如果類有虛擬成員函式或者虛擬繼承父類(即有虛擬基類)時;
2、如果類的基類有構造函式(可以是用戶定義的構造函式,或編譯器提供的默認構造函式);
3、在類中的所有非靜態的對象數據成員,它們對應的類中有構造函式(可以是用戶定義的構造函式,或編譯器提供的默認構造函式)。
<類名>::<類名>(){},即不執行任何操作。
例子
#include <iostream>using namespace std;class time{public:    time()//constructor.構造函式    {        hour=0;        minute=0;        sec=0;    }    void set_time();    void show_time();private:    int hour, minute, sec;};int main(){    class time t1;    t1.show_time();    t1.set_time();    t1.show_time();    return 0;}void time::set_time(){    cin>>hour>>minute>>sec;}void time::show_time(){    cout<<hour<<":"<<minute<<":"<<sec<<endl;}
程式運行情況:
0:0:0
10 11 11 回車
10:11:11
任何時候,只要創建類或結構,就會調用它的構造函式。類或結構可能有多個接受不同參數的構造函式。構造函式使得程式設計師可設定默認值、限制實例化以及編寫靈活且便於閱讀的代碼。
PHP的構造函式
void__construct( [mixed args [, ...]] )
php 5 允行開發者在一個類中定義一個方法作為構造函式。具有構造函式的類會在每次創建對象時先調用此方法,所以非常適合在使用對象之前做一些初始化工作。
注:如果子類中定義了構造函式則不會暗中調用其父類的構造函式。要執行父類的構造函式,需要在子類的構造函式中調用parent::__construct()
例子 使用新標準的構造函式
<?phpclassBaseClass{function__construct(){print"InBaseClassconstructor/n";}}classSubClassextendsBaseClass{function__construct(){parent::__construct();print"InSubClassconstructor/n";}}$obj=newBaseClass();$obj=newSubClass();?>
為了實現向後兼容性,如果 php 5 在類中找不到__construct()函式,它就會嘗試尋找舊式的構造函式,也就是和類同名的函式。因此唯一會產生兼容性問題的情況是:類中已有一個名為__construct()的方法,但它卻又不是構造函式。
Python的構造函式
定義格式為
class <類名>:
__init__(self [,參數表]):
#函式體
#其它的方法和屬性

其他特點

1.它的函式名與類名相同;
2.它可以重載;
3.不能指定返回類型,即使是void也不行;
4.雖然在一般情況下,構造函式不被顯式調用,而是在創建對象時自動被調用。但是並不是不能被顯式調用。有些時候是一定要顯式調用的,只要是父類有帶參的構造函式,在子類中就必須顯式的調用父類的構造函式,因為子類的構造器在實例化時無法找到父類的構造函式(當父類有自己寫的無參構造函式時,子類也不用顯式調用)。
void__destruct( void )
php 5 引入了析構函式的概念,這類似於其它面向對象的語言,如 C++。析構函式會在到某個對象的所有引。

語法

  • Java, C++, C#, ActionScriptPHP 4中的命名規範會要求構造器函式的名稱與它所在類的名稱相同。
  • PHP 5 建議的構造器函式名稱為__construct。為了保證向下兼容,__construct方法無法找到時會調用任何跟類名同名的方法作為構造器。從 PHP 5.3.3 起,這種途徑只對非名字空間的類有效。
  • Perl里,構造器被約定俗成地命名為"new",並且會完成創建對象的大量工作。
  • 在 Perl 的 Moose 對象系統中,構造函式(叫做 new)是自動生成的,程式設計師可以通過指定一個 BUILD 方法來對其進行擴充。
  • Visual Basic .NET里,構造器被命名為New,是個 Sub。
  • Python里構造器的被分為 __new__ 和 __init__ 兩個方法。__new__方法負責為實例分配內儲存空間,並接受自身的類作為參數(一般命名為 cls)。__init__方法接受被新建的實例作為參數(一般稱為 self)。
  • Object Pascal 的構造函式用關鍵字 constructor 標識,並且可以起任意名字(但一般來說會被起名為 Create)。
  • Objective-C 的構造函式分成兩個方法,alloc 和 init。alloc 方法分配記憶體,init 負責初始化。new 方法會調用 alloc 和 init 兩者。

記憶體機制

在 Java, C# 和 VB .NET 里,構造器會在一種叫做的特殊數據結構里創建作為引用類型的實例。值類型(例如 int, double 等等)則會創建在叫做的有序數據結構里。VB .NET and C# 會允許用new來創建值類型的實例。然而在這些語言裡,即使使用這種方法創建的對象依然只會在棧里。
在 C++ 里,不用 new 創建的對象會保存在棧里,使用 new 創建時則會在堆里。它們必須分別使用析構函式或者delete操作才能被刪除。

語言細節

Java

在Java里,構造器和其他方法的主要差別在於:
  • 構造器不具有任何顯性返回類型。
  • 構造器無法被直接“new” invokes them).
  • 構造器無法被標示為synchronized, final, abstract, native, 或者static
Java 里的構造器會按照以下順序完成下列工作:
  1. 將類變數初始到預設值。(byte, short, int, long, float, 和 double 變數會默認設為它們相應的0值,booleans 會被設為 false, chars 會被設為空字元('\u0000'),對象引用會被設為 null)
  2. 引用父類的構造器,如果沒有定義任何構造器。
  3. 將實例變數初始化到指定值。
  4. 執行構造器內的代碼。
在 Java 中可以通過關鍵字super訪問父類的構造器。
public class Example{    // Definition of the constructor.    public Example()    {        this(1);    }    // Overloading a constructor    public Example(int input)    {        data = input; // This is an assignment    }    // Declaration of instance variable(s).    private int data;} 
// Code somewhere else// Instantiating an object with the above constructorExample e = new Example(42);
不接收任何參數的構造器被稱作“無參數構造器”。

Visual Basic .NET

Visual Basic .NET中, 構造函式以"New"為定義方法,並且必須是個 Sub。
Class Foobar    Private strData As String    ' Constructor    Public Sub New(ByVal someParam As String)        strData = someParam    End SubEnd Class
' code somewhere else' instantiating an object with the above constructorDim foo As New Foobar(".NET")

C#

public class MyClass{    private int a;    private string b;    // Constructor    public MyClass() : this(42, "string")    {    }    // Overloading a constructor    public MyClass(int a, string b)    {        this.a = a;        this.b = b;    }}
// Code somewhere// Instantiating an object with the constructor aboveMyClass c = new MyClass(42, "string");
C# 靜態構造函式
C#中,靜態構造函式是用來初始化任何靜態數據。靜態構造函式也稱為“類構造函式”,由於類構造函式在生成的 MSIL 里名為“.cctor”,因此也被稱為“cctor”。
靜態構造函式允許複雜的靜態變數初始化。
靜態構造函式在該類第一次被訪問時調用,任何使用該類的操作(無論是調用靜態函式、屬性還是訪問靜態變數,還是構造類的實例)都會引發靜態構造函式的執行。靜態構造函式是執行緒安全的,並且是單例的。當用在泛型類中時,靜態構造函式對於泛型的每個實例化都調用一次。靜態變數也同樣如此。
public class MyClass{    private static int _A;    // Normal constructor    static MyClass()    {        _A = 32;    }    // Standard default constructor    public MyClass()    {    }}// Code somewhere// Instantiating an object with the constructor above// right before the instantiation// The variable static constructor is executed and _A is 32MyClass c = new MyClass();

C++

C++ 的構造函式以該類的類名為標識,且不寫返回值類型也無法返回值:
class C{public:  C(void){    ...  }};
構造函式的函式體執行是在各個成員構造完之後才開始,因此要想更改成員的構造方式需要使用成員初始化列表:
class D: public B{public:  D(void): B("Hello, world!"){    ...  }};
複製構造函式接受同類對象的左值引用(一般為 const T &)、移動構造函式接受右值引用(一般為 T&&):
class E{public:  E(const E &e){...}//Copy constructor  E(E &&e){...}//Move constructor};
C++ 中,程式設計師若未對某類定義構造函式(以及賦值函式、析構函式),編譯器在滿足條件時會定義相應的函式。

Ruby

irb(main):001:0> class ExampleClassirb(main):002:1>   def initializeirb(main):003:2>     puts "Hello there"irb(main):004:2>   endirb(main):005:1> end=> nilirb(main):006:0> ExampleClass.newHello there=> #<ExampleClass:0x007fb3f4299118>

相關詞條

熱門詞條

聯絡我們