构造器

在类别基础的面向对象程序设计中，构造器（英语： Constructor，有时简称 ctor），别称：构造方法、构造函数、建构子、建构式）是一个-{zh-hans:类;zh-hant:类别;}--{zh-hans:里;zh-hant:里}-用于建立对象的特殊子程序。它能初始化一个新建的对象，并时常会接受参数用以设定变量。
构造器跟一般的实例方法十分相似；但是与其它方法不同，构造器没有返回类型，不会被继承，且不会有范围修饰符。构造器的函数名称一般与它所属的-{zh-hans:类;zh-hant:类别;}-的名称相同(Python语言除外)。 它承担着初始化对象数据成员并建立类不变象的任务；在-{zh-hans:类;zh-hant:类别;}-不变象无效的时候它会失败。一个正确编写的构造器会使它生成的对象保持在一个"有效"状态。不可变物件必须在构造器内完成所有初始化。
多数编程语言允许构造器重载 - 一个-{zh-hans:类;zh-hant:类别;}-被允许拥有多个接受不同参数种类的构造器同时存在。一些编程语言允许某些特殊种类的构造器。使用单个-{zh-hans:类;zh-hant:类别;}-来具体地建立和返回新实例的构造器，时常被抽象为工厂方法 - 一种同样用来建立新对象，但会同时使用多个-{zh-hans:类;zh-hant:类别;}-，或者一些诸如对象池的分配方案来完成这一过程的子程序。
种类.
参数化构造器.
接收参数的构造器被称为参数化构造器。参数的数量可以大于或等于一。例如，在C++中：<syntaxhighlight lang="cpp">
class Example
Example :: Example()
Example :: Example(int a, int b)
</syntaxhighlight>使用参数化构造器声明对象时，必须传入初始值作为构造器的参数。在这种情况下，一般的声明对象的方法可能不再适用。
构造器函数的调用方式可以分为显式和隐式两种。<syntaxhighlight lang="cpp">
</syntaxhighlight>
缺省构造器.
如果在编写一个可实例化的类时没有专门编写构造器，多数编程语言会自动生成缺省构造器。
缺省构造器的特性依不同语言而定。某些情况下它会将所有的实例变量同时初始化到0，或者任何其他别的值；某些缺省构造器什么也不会做。
某些语言 (Java, C#, VB .NET) 会缺省构造由该类类型定义的数组，使其充满空值引用。没有空值引用的语言一般会禁止缺省构造包含不可缺省构造对象的数组，或者要求在建立时专门初始化这些数值 (C++):<syntaxhighlight lang="cpp">
class student{
int main() {
</syntaxhighlight>
转换建构子.
转换建构子可定义从使用者定义或内建类型转换成使用者定义类型的作业。
复制建构子.
复制建构子（英语：Copy constructor）是C++程式语言中的一种特别的建构子，习惯上用来建立一个全新的物件，这个全新的物件相当于已存在物件的副本。这个建构子只有一个参数（引数）：就是用来复制物件的参照（常用const修饰）。建构子也可以有更多的参数，但除了最左第一个参数是该类别的参照类别型外，其它参数必须有预设值。
移动建构子.
移动构造函数（英语：Move constructor）是 C++11 中新增的一种构造函数，用来避免多余的分配新内存——复制——销毁旧内存的操作。参见 C++11 条目内的介绍。
内存机制.
在 Java, C# 和 VB .NET 里，构造器会在一种叫做堆积的特殊记忆体结构里建立作为引用类型的实例。数值类型（例如 int, double 等等）则会建立在叫做堆叠的有序数据结构中。VB .NET and C# 会允许用codice_17来建立值类型的实例。然而在这些语言中，即使使用这种方法建立的对象依然只会在栈上。
在 C++ 中，不用 new 建立的对象会保存在栈上，使用 new 建立时则会在堆积上。它们必须分别使用析构函数或者 delete 操作才能被删除。
语言细节.
Java.
在Java里，构造器和其他方法的主要差别在于：
Java 里的构造器会按照以下顺序完成下列工作：
在 Java 中可以通过关键词 codice_22 访问父类的构造器。<syntaxhighlight lang="java">
public class Example
</syntaxhighlight><syntaxhighlight lang="java">
// Code somewhere else
// Instantiating an object with the above constructor
Example e = new Example(42);
</syntaxhighlight>不接收任何参数的构造器被称作“无参数构造器”。
Visual Basic .NET.
在Visual Basic .NET中, 建构子以"codice_3"为定义方法，并且必须是个 Sub。<syntaxhighlight lang="vbnet">
Class Foobar
End Class
</syntaxhighlight><syntaxhighlight lang="vbnet">
' code somewhere else
' instantiating an object with the above constructor
Dim foo As New Foobar(".NET")
</syntaxhighlight>
C#.
<syntaxhighlight lang="csharp">
public class MyClass
</syntaxhighlight><syntaxhighlight lang="csharp">
// Code somewhere
// Instantiating an object with the constructor above
MyClass c = new MyClass(42, "string");
</syntaxhighlight>
C# 静态建构子.
在C#中,"静态建构子"是用来初始化任何静态资料。静态构造函数也称为“类构造函数”，由于类构造函数在生成的 MSIL 里名为“.cctor”，因此也被称为“cctor”。
静态构造函数允许复杂的静态变量初始化。
静态构造函数在该类第一次被访问时调用，任何使用该类的操作（无论是调用静态函数、属性还是访问静态变量，还是构造类的实例）都会引发静态构造函数的执行。静态构造函数是线程安全的，并且是单例的。当用在泛型类中时，静态构造函数对于泛型的每个实例化都调用一次。静态变量也同样如此。<syntaxhighlight lang="csharp">
public class MyClass
</syntaxhighlight><syntaxhighlight lang="csharp">
// 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();
</syntaxhighlight>
C++.
C++ 的构造函数以该-{zh-cn:类;zh-tw:类别}-的名称为标识，且不须写-{zh-cn:返回值类型;zh-tw:回传值型别;}-也无法-{zh-cn:返回值;zh-tw:回传数值}-：
<syntaxhighlight lang="cpp">
class C{
public:
</syntaxhighlight>
构造函数的函数体执行是在各个成员构造完之后才开始，因此要想更改成员的-{zh-tw:建构;zh-cn:构造;}--{zh-cn:方式;zh-tw:方法}-需要使用成员初始化列表：
<syntaxhighlight lang="cpp">
class B{
public:
</syntaxhighlight>
基类的方式与成员相同，是在初始化列表中写基类名、接构造函数参数表：
<syntaxhighlight lang="cpp">
class D: public B{
public:
</syntaxhighlight>
复制构造函数接受同类对象的左值引用（一般为 const T &）、移动构造函数接受右值引用（一般为 T&&）：
<syntaxhighlight lang="cpp">
class E{
public:
};
</syntaxhighlight>
C++ 中，程序员若未对某类定义构造函数（以及赋值函数、析构函数），编译器在满足条件时会定义相应的函数，参见 等页面。
CFML.
<syntaxhighlight lang="javascript">
component initmethod="Cheese" {
</syntaxhighlight>
Object Pascal.
<syntaxhighlight lang="delphi">
program OopProgram;
type
constructor TPerson.Create(AName: string);
begin
end;
var
begin
end.
</syntaxhighlight>
Perl.
<syntaxhighlight lang="perl">
package Person;
sub new {
1;
</syntaxhighlight>
Perl with Moose.
<syntaxhighlight lang="perl">
package Person;
use Moose;
has first_name => (is => 'ro', isa => 'Str', required => 1);
has last_name => (is => 'ro', isa => 'Str', required => 1);
has age => (is => 'rw', isa => 'Int', predicate => 'has_age');
sub BUILD {
1;
</syntaxhighlight>
PHP.
<syntaxhighlight lang="php">
class Person
</syntaxhighlight>
Python.
<syntaxhighlight lang="pycon">
Â»> 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
</syntaxhighlight>
Ruby.
<syntaxhighlight lang="rbcon">
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>
</syntaxhighlight>