class Foo {
public:
Foo() { Foo(1)}
Foo(int x, int y = 0):i(x) {}
private:
int i;
}
有人可以给我一些理由我可以这样做吗?如果不是为什么?
答案 0 :(得分:10)
因为语言规范不允许它。就像语言一样。如果您习惯使用Java或其他允许它的语言,那会非常烦人。但是,你会在一段时间后习惯它。所有语言都有它们的怪癖,这只是C ++的一个。我确信这些规格的作者有他们的理由。
我发现最好的方法是创建一个通用的初始化函数,让两个构造函数都调用它。
这样的事情:
class Foo {
public:
Foo() {initialize(1);}
Foo(int nX) { initialize(nx); }
private:
void initialize(int nx) { x=nx; }
int x;
};
答案 1 :(得分:4)
这是语言设计的选择。
构造函数是一次(每个对象)操作,它在未初始化的内存中创建一个新对象。只有一个构造函数可以为对象调用,一旦它完成了对象的生命周期开始,就不能在该对象上调用或恢复其他构造函数。
在其生命的另一端,析构函数只能(有效地)被调用每个对象一次,并且一旦进入析构函数,对象的生命周期就结束了。
这样做的一个主要原因是当一个对象析构函数运行时它是明确的,以及它可以指望该对象处于什么状态。
如果一个类构造函数成功完成,那么它的析构函数将被调用,否则该对象的生命周期从未开始,并且不会调用析构函数。当对象在其构造函数中获取需要在其析构函数中释放的资源时,此保证可能很重要。如果资源获取失败,那么通常会使构造函数失败;如果析构函数仍然运行,它可能会尝试释放从未成功获取的资源。
如果允许构造函数相互调用,则可能不清楚调用或被调用的构造函数是否负责该资源。例如,如果调用的构造函数在被调用的构造函数返回后失败,那么析构函数是否应该运行?被调用的构造函数可能已经获得了需要释放的东西,或者这可能导致调用构造函数失败并且不应该调用析构函数,因为资源句柄永远不会有效。
为简化破坏规则,如果每个对象由单个构造函数创建,并且 - 如果成功创建 - 由单个析构函数销毁,则更简单。
请注意,在C ++ 11中,构造函数可以委托给不同的构造函数,但是有一些限制并没有真正放松每个对象的一个构造的主体。 (主要构造函数可以转发到目标构造函数,但如果它的话,它不能在其初始化列表中命名任何其他内容(基类或成员)。一旦目标构造函数返回主体,它们将由目标构造函数初始化。 prinicipal构造函数将完成(进一步初始化)。虽然它允许你在构造函数之间共享构造函数代码,但是不可能重新构造任何基础或成员。)
答案 2 :(得分:2)
你不能这样做。见第10.3节:http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.3。您可以尝试这样做,但这样做会构造一个新的临时对象(而不是这个)并在控件移动时被销毁。
然而,您可以创建一个初始化变量的私有函数,一个默认构造函数或参数化构造函数都可以调用的函数。
答案 3 :(得分:2)
我曾经看到过一个非常可怕的黑客攻击另一个ctor。它在this指针上使用放置新操作。 ERK
像这样:
Class::Class(int x) : x_(x) {}
Class::Class() {
new (this) Class(0);
}
Class::Class(const Class &other) : x_(other.x_) {}
Class& operator=(const Class &other) {
new (this) Class(other);
return *this;
}
请注意,我不推荐这个,我不知道它可能会对C ++结构(如虚拟基类等)造成什么可怕的影响。但我希望有一些。
答案 4 :(得分:0)
虽然根据标准,供应商可以自己的方式自由地实现数据绑定,但如果我们考虑最流行的实现:这个指针,我们可以看到无法实现这一点的原因。
假设您有一个班级:
class A
{
public:
A(){}
A(int a){}
} ;
使用this指针实现,这个类看起来像:
class A
{
public:
A(A *this){}
A(A *this,int a){}
} ;
通常你会创建这样的对象:
A ob ;
现在,当编译器看到这个时,它会为此分配内存,并将此分配的内存块的地址传递给A的构造函数,然后构造该对象。它会尝试每次为每个被称为。
的构造函数执行相同的操作现在,当您尝试在另一个构造函数中调用构造函数时,编译器应该传递当前对象,而不是分配新内存。因此不一致!
然后我看到的另一个原因是,即使您可能想在另一个内部调用构造函数,您仍然希望构造函数为类中的所有对象调用默认构造函数。现在,如果一个构造函数调用另一个构造函数,则默认构造应该发生在第一个构造函数而不是后续构造函数。实现此行为意味着需要处理多个排列。如果没有,则性能降低,因为每个构造函数将默认构造所有包含的对象。
这是我可以想到的这种行为的可能原因,并且没有任何标准可以支持。