在类别基础的面向对象程序设计中，**构造器**（英语： **Constructor**，有時簡稱 ctor），别称：**构造方法**、**构造函数**、**建构子、建構式**）是一个用于建立对象的特殊子程序。它能初始化一个新建的对象，并时常会接受参数用以设定实例（英语：）变量。

构造器跟一般的实例方法十分相似；但是与其它方法不同，构造器没有返回类型（英语：），不会被继承，且不会有范围修饰符。构造器的函数名称一般与它所属的的名称相同。 它承担着初始化对象数据成员并建立类不变象的任务；在不变象无效的时候它会失败。一个正确编写的构造器会使它生成的对象保持在一个*有效*状态。不可变物件必须在构造器内完成所有初始化。

多数编程语言允许构造器重载 - 一个被允许拥有多个接受不同参数（英语：）种类的构造器同时存在。一些编程语言允许某些特殊种类的构造器。使用单个来具体地建立和返回新实例的构造器，时常被抽象为工厂方法 - 一种同样用来建立新对象，但会同时使用多个，或者一些诸如对象池的分配方案来完成这一过程的子程序。

种类
--

### 参数化构造器

接收参数的构造器被称为**参数化构造器**。参数的数量可以大于或等于一。例如，在C++中：

```
class Example
{
 int x, y;
 public:
 Example();
 Example(int a, int b); // Parameterized constructor
};
Example :: Example()
{
}
Example :: Example(int a, int b)
{
 x = a;
 y = b;
}

```
使用参数化构造器声明对象时，必须传入初始值作为构造器的参数。在这种情况下，一般的声明对象的方法可能不再适用。

构造器函数的调用方式可以分为显式和隐式两种。

```
 Example e = Example(0, 50); // Explicit call

 Example e(0, 50); // Implicit call

```

### 缺省构造器

如果在编写一个可实例化的类时没有专门编写构造器，多数编程语言会自动生成缺省构造器。

缺省构造器的特性依不同语言而定。某些情况下它会将所有的实例变量同时初始化到0，或者任何其他别的值；某些缺省构造器什么也不会做。

某些语言 (Java, C#, VB .NET) 会缺省构造由该类类型定义的数组，使其充满空值引用。没有空值引用的语言一般会禁止缺省构造包含不可缺省构造对象的数组，或者要求在建立时专门初始化这些数值 (C++):

```
#include <iostream>

class student{
 public:
 int a,b;
 student(a=0,b=0) //default constructor
};

int main() {
}

```

### 轉換建構子

轉換建構子可定義從使用者定義或內建類型轉換成使用者定義類型的作業。

### 複製建構子

複製建構子（英語：Copy constructor）是C++程式語言中的一種特別的建構子，習慣上用來建立一個全新的物件，這個全新的物件相當於已存在物件的副本。這個建構子只有一個參數（引數）：就是用來複製物件的參照（常用const修飾）。建構子也可以有更多的參數，但除了最左第一個參數是該類別的參照類別型外，其它參數必須有預設值。

### 移動建構子

移动构造函数（英语：Move constructor）是 C++11 中新增的一种构造函数，用来避免多余的分配新内存——复制——销毁旧内存的操作。参见 C++11 条目内的介绍。

语法
--

* Java, C++, C#, ActionScript 和 PHP 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`"啟動。
* 构造器无法被標示為*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 constructor
Example 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 Sub
End Class

```

```
' code somewhere else
' instantiating an object with the above constructor
Dim 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 above
MyClass 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 32
MyClass c = new MyClass();

```

### C++

C++ 的构造函数以该的名稱为标识，且不須写也无法：

```
class C{
public:
 C(void){
 ...
 }
};

```

构造函数的函数体执行是在各个成员构造完**之后**才开始，因此要想更改成员的需要使用成员初始化列表：

```
class B{
public:
 std::string str;
 B(const char \*psz): str(psz){
 ...
 }
};

```

基类的方式与成员相同，是在初始化列表中写基类名、接构造函数参数表：

```
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++ 中，程序员若未对某类定义构造函数（以及赋值函数、析构函数），编译器在满足条件时会定义相应的函数，参见  等页面。

### F#

### Eiffel

### CFML

```
component initmethod="Cheese" {
 // properties
 property name="cheeseName";

 // constructor
 function Cheese Cheese( required string cheeseName ) {
 variables.cheeseName = arguments.cheeseName;
 return this;
 }
}

```

### Object Pascal

```
program OopProgram;

type
 TPerson = class
 private
 FName: string;
 public
 property Name: string read FName;
 constructor Create(AName: string);
 end;

constructor TPerson.Create(AName: string);
begin
 FName := AName;
end;

var
 Person: TPerson;
begin
 Person := TPerson.Create('Peter'); // allocates an instance of TPerson and then calls TPerson.Create with the parameter AName = 'Peter'
end.

```

### Perl

```
package Person;
# In Perl constructors are named 'new' by convention.
sub new {
 # Class name is implicitly passed in as 0th argument.
 my $class = shift;

 # Default attribute values, if you have any.
 my %defaults = ( foo => "bar" );

 # Initialize attributes as a combination of default values and arguments passed.
 my $self = { %defaults, @\_ };

 # Check for required arguments, class invariant, etc.
 if ( not defined $self->{first\_name} ) {
 die "Mandatory attribute missing in Person->new(): first\_name";
 }
 if ( not defined $self->{last\_name} ) {
 die "Mandatory attribute missing in Person->new(): last\_name";
 }
 if ( defined $self->{age} and $self->{age} < 18 ) {
 die "Invalid attribute value in Person->new(): age < 18";
 }

 # Perl makes an object belong to a class by 'bless'.
 bless $self, $class;
 return $self;
}
1;

```

### Perl with Moose

```
package Person;
# enable Moose-style object construction
use Moose;

# first name ( a string) can only be set at construction time ('ro')
has first\_name => (is => 'ro', isa => 'Str', required => 1);
# last name ( a string) can only be set at construction time ('ro')
has last\_name => (is => 'ro', isa => 'Str', required => 1);
# age (Integer) can be modified after construction ('rw'), and is not required
# to be passed to be constructor. Also creates a 'has\_age' method which returns
# true if age has been set
has age => (is => 'rw', isa => 'Int', predicate => 'has\_age');

# Check custom requirements
sub BUILD {
 my $self = shift;
 if ($self->has\_age && $self->age < 18) { # no under 18s
 die "No under-18 Persons";
 }
}
1;

```

### PHP

```
class Person
{
    private $name;

    public function \_\_construct($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }
}

```

### Python

```
>>> class ExampleClass(object):
...     def \_\_new\_\_(cls, value):
...         print("Creating new instance...")
...         # Call the superclass constructor to create the instance.
...         instance = super(ExampleClass, cls).\_\_new\_\_(cls)
...         return instance
...     def \_\_init\_\_(self, value):
...         print("Initialising instance...")
...         self.payload = value
>>> exampleInstance = ExampleClass(42)
Creating new instance...
Initialising instance...
>>> print(exampleInstance.payload)
42

```

### Ruby

```
irb(main):001:0> class ExampleClass
irb(main):002:1>  def initialize
irb(main):003:2>  puts "Hello there"
irb(main):004:2>  end
irb(main):005:1> end
=> nil
irb(main):006:0> ExampleClass.new
Hello there
=> #<ExampleClass:0x007fb3f4299118>

```

注釋
--

參見
--

* 缺省构造函数
* 複製建構子

參考來源
----

1. ↑ .  [2016-05-11]. （原始内容存档于2016-06-16）.
2. ↑  Constructors and Destructors （页面存档备份，存于）, from PHP online documentation
3. ↑  Data model （页面存档备份，存于）, from Python online documentation
4. ↑ . Oracle Corporation. 2013  [2013-12-20]. （原始内容存档于2021-12-03）.
5. ↑ . Eric Lippert. 2013-02-06  [2014-04-05]. （原始内容存档于2017-07-07）.
6. ↑ . APress. 2006-01-01  [2014-04-05]. （原始内容存档于2015-04-14）.
7. ↑ .  [2016-03-30]. （原始内容存档于2016-10-30）.
8. ↑ . cppreference.  [2016-10-29]. （原始内容存档于2020-12-30）.
9. ↑ . cppreference.  [2016-10-29]. （原始内容存档于2020-11-12）.
10. ↑ . cppreference.  [2016-10-29]. （原始内容存档于2021-03-05）.
11. ↑ . cppreference.  [2016-10-29]. （原始内容存档于2021-01-16）.
12. ↑ . cppreference.  [2016-10-29]. （原始内容存档于2020-11-12）.
13. ↑ . cppreference.  [2016-10-29]. （原始内容存档于2021-03-02）.