C ++中的构造函数

时间:2010-04-12 17:43:51

标签: c++ constructor language-design

为什么构造函数的名称与类名相同?

10 个答案:

答案 0 :(得分:10)

根据Stroustrup的说法,因为新功能的替代“一直是混乱的根源”。参见The Design& C ++的演变,第3.11.2节,虽然这是我引用的完整理由。

编辑:正如人们所指出的那样,有许多替代解决方案。例如Smalltalk,这样做:

myclass new

向myclass类对象发送“新”消息。显然,这里的C ++解决方案有点傻了:

myclass myclass

显然不明智。

Delphi,OTOH,允许任何命名函数作为构造函数,通过标记它:

constructor Create;
constructor FooBar;

对于任何类都是OK构造函数名称。与Smalltalk一样,您需要在类对象上调用它们:

myclass.Create;

在所有这些解决方案中,我认为C ++是最优雅的,我可以理解为什么它几乎被后继语言普遍采用。

答案 1 :(得分:9)

C ++语言标准:

  

<强> 12.1。构造函数没有名称。

你的问题是基于混乱。构造函数使用特殊声明语法,其中再次使用类名来代替成员名。我没有看到这种语法有什么问题,所以我甚至无法想象会触发你的问题(这使得它很难回答,如果不是不可能的话)。

然而,C ++中的构造函数没有名称。它们根本不需要名称,因为在设计中,C ++中没有必须引用构造函数的上下文。

答案 2 :(得分:5)

在最初的“C with classes”中它实际上并非 - 它被命名为“new”,IIRC。无论如何,对于关于C ++的大多数“为什么”的问题,你可以在“C ++的设计和演变”一书中找到答案。

答案 3 :(得分:3)

实际上,它不一样。 12.1 / 1:

  

构造函数没有名称

调用构造函数的唯一方法是使用特定的对象构造/转换语法:函数名称查找找不到它,并且您不能获取构造函数的地址。这可能是一件好事。

我想用于声明构造函数的语法可能看起来像这样:

struct Foo {
    int a;
    constructor(int a) : a(a) { }
};

但这需要额外的保留字constructor。这意味着声明构造函数的代码看起来不像构造对象的代码。唯一的“好处”是释放“Foo”以用作成员函数名称。这听起来对我来说非常有用,特别是因为你失去了“构造函数”作为成员函数名。如果对Foo作为成员函数名称有任何强烈抗议,我想它可能已经有所不同,例如通过使用稍微不同的语法来声明一个构造函数(+ Foo,与~Foo一起使用,也许?)。所以我猜没有。

我无法立即看到在C ++中使用“用户命名的构造函数”有任何意义。如果你想要一个Foo的静态成员函数来获取某些参数并返回一个Foo,你可以这样声明它:

struct Foo {
    static Foo bar(int);
};

和“将它用作构造函数”,如下所示:

Foo f = Foo::bar(12);

答案 4 :(得分:2)

如果您希望构造函数将基类的构造函数作为初始化程序调用,则需要指定其构造函数名称。如果他们都被命名为相同,那将是困难的。 e.g。

class Animal {
public:
   Animal();
};

class Dog {
public:
   Dog();
};

Animal::Animal() {
   // Base class constructor
}

Dog::Dog() : Animal() {
   // Derived class constructor, calling the base constructor as an initializer
}

答案 5 :(得分:1)

因为这就是语言规范所说的。在像Python这样的语言中,它不是。

答案 6 :(得分:1)

这只是语言定义的问题。编译器知道具有相同名称的方法是构造函数。这也使得该类的对象的制作非常清晰,任何不知道该类的人都知道如果名称等于这就是构造函数。

答案 7 :(得分:0)

有哪些替代方案?也许:

  • 创建一个新关键字以指定构造函数
  • 为所有构造函数设置一个名称(例如new())。

这两种选择似乎都不如现实。

答案 8 :(得分:0)

我假设你是C ++的新手,甚至可能是面向对象的编程。所以,首先,我希望您了解类构造函数是什么。

大多数类型都有某种构造函数,用于初始化自身。即使在谈论int原语或其他类型的变量时,一切都可以初始化²。因此,在制作类时,系统会要求您提供名为构造函数的初始化程序。构造函数可以具有可能是必需的参数。它们也可以重载,这意味着一个类可以有许多构造函数。

由于构造函数是初始化函数,因此对它们的调用是隐式的:每次创建该类的对象时都会调用类构造函数,无论是使用new关键字还是在堆栈中声明它:

CMyObject obj;

现在,他们必须在你的班级内宣布。毕竟它们是方法......那么,它的名字应该是什么?例如,Python采用不同的方法并使用关键字__init__来执行此操作; C ++的设计师决定它将成为该类的名称。

这是有道理的,因为毕竟拥有一个带有类名的成员方法可能会导致系统中的名称冲突(歧义)。 (尽管this series篇文章是关于C#的,但它澄清了为什么将名称用于具有相同名称的特定范围的成员是错误的)

²但有时它们不是为了减少执行时间成本。

答案 9 :(得分:0)

每次创建对象时都会调用构造函数,这通常会自动发生,即编译器调用构造函数,这是一个没有返回数据类型的函数调用。因此,C ++语言决定将此函数命名为类的名称。