Sto*_*net 879 c++ constructor
作为C#开发人员,我习惯于运行构造函数:
class Test {
public Test() {
DoSomething();
}
public Test(int count) : this() {
DoSomethingWithCount(count);
}
public Test(int count, string name) : this(count) {
DoSomethingWithName(name);
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在C++中执行此操作?
我尝试调用类名并使用'this'关键字,但都失败了.
Joh*_*dol 1175
C++ 11:是的!
C++ 11及更高版本具有相同的功能(称为委托构造函数).
语法与C#略有不同:
class Foo {
public:
Foo(char x, int y) {}
Foo(int y) : Foo('a', y) {}
};
Run Code Online (Sandbox Code Playgroud)
C++ 03:没有
不幸的是,在C++ 03中没有办法做到这一点,但有两种模拟方法:
您可以通过默认参数组合两个(或更多)构造函数:
class Foo {
public:
Foo(char x, int y=0); // combines two constructors (char) and (char, int)
// ...
};
Run Code Online (Sandbox Code Playgroud)使用init方法共享公共代码:
class Foo {
public:
Foo(char x);
Foo(char x, int y);
// ...
private:
void init(char x, int y);
};
Foo::Foo(char x)
{
init(x, int(x) + 7);
// ...
}
Foo::Foo(char x, int y)
{
init(x, y);
// ...
}
void Foo::init(char x, int y)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)请参阅C++ FAQ条目以供参考.
Cyr*_* Ka 108
不,你不能在C++ 03中调用另一个构造函数(称为委托构造函数).
这在C++ 11(又名C++ 0x)中有所改变,它增加了对以下语法的支持:(
来自维基百科的示例)
class SomeType
{
int number;
public:
SomeType(int newNumber) : number(newNumber) {}
SomeType() : SomeType(42) {}
};
Run Code Online (Sandbox Code Playgroud)
ohl*_*her 40
我相信你可以从构造函数中调用构造函数.它将编译并运行.我最近看到有人这样做,它在Windows和Linux上运行.
它只是没有做你想要的.内部构造函数将构造一个临时本地对象,一旦外部构造函数返回,该对象就会被删除.它们也必须是不同的构造函数,否则您将创建递归调用.
参考:https://isocpp.org/wiki/faq/ctors#init-methods
kch*_*se2 21
值得指出的是,您可以在构造函数中调用父类的构造函数,例如:
class A { /* ... */ };
class B : public A
{
B() : A()
{
// ...
}
};
Run Code Online (Sandbox Code Playgroud)
但是,不,你不能调用同一个类的另一个构造函数.
Ben*_*n L 20
class Foo {
int d;
public:
Foo (int i) : d(i) {}
Foo () : Foo(42) {} //New to C++11
};
Run Code Online (Sandbox Code Playgroud)
此外,成员也可以像这样初始化.
class Foo {
int d = 5;
public:
Foo (int i) : d(i) {}
};
Run Code Online (Sandbox Code Playgroud)
这应该消除了创建初始化辅助方法的需要.并且仍然建议不要在构造函数或析构函数中调用任何虚函数,以避免使用任何可能未初始化的成员.
lyn*_*gvi 13
如果你想成为邪恶的,你可以使用就地"新"运算符:
class Foo() {
Foo() { /* default constructor deliciousness */ }
Foo(Bar myParam) {
new (this) Foo();
/* bar your param all night long */
}
};
Run Code Online (Sandbox Code Playgroud)
似乎为我工作.
编辑
正如@ElvedinHamzagic指出的那样,如果Foo包含一个分配内存的对象,那么该对象可能不会被释放.这使事情进一步复杂化.
一个更一般的例子:
class Foo() {
private:
std::vector<int> Stuff;
public:
Foo()
: Stuff(42)
{
/* default constructor deliciousness */
}
Foo(Bar myParam)
{
this->~Foo();
new (this) Foo();
/* bar your param all night long */
}
};
Run Code Online (Sandbox Code Playgroud)
看起来有点不那么优雅,当然.@ JohnIdol的解决方案要好得多.
不,在C++中,您无法从构造函数中调用构造函数.沃伦指出,你能做的是:
请注意,在第一种情况下,您无法通过从另一个构造函数调用来减少代码重复.您当然可以使用一个单独的private/protected方法来执行所有初始化,并让构造函数主要处理参数处理.
另一个尚未显示的选项是将您的类拆分为两个,在您的原始类周围包装一个轻量级接口类,以实现您正在寻找的效果:
class Test_Base {
public Test_Base() {
DoSomething();
}
};
class Test : public Test_Base {
public Test() : Test_Base() {
}
public Test(int count) : Test_Base() {
DoSomethingWithCount(count);
}
};
Run Code Online (Sandbox Code Playgroud)
如果您有许多构造函数必须调用它们的“下一级”对应物,这可能会变得混乱,但对于少数构造函数,它应该是可行的。
小智 5
在Visual C++中,您还可以在构造函数中使用此表示法:this-> Classname :: Classname(另一个构造函数的参数).请参阅以下示例:
class Vertex
{
private:
int x, y;
public:
Vertex(int xCoo, int yCoo): x(xCoo), y(yCoo) {}
Vertex()
{
this->Vertex::Vertex(-1, -1);
}
};
Run Code Online (Sandbox Code Playgroud)
我不知道它是否在其他地方工作,我只在Visual C++ 2003和2008中测试过它.你也可以用这种方式调用几个构造函数,我想,就像在Java和C#中一样.
PS:坦率地说,我很惊讶这是前面没有提到的.
小智 5
简而言之,您不能在C ++ 11之前。
C ++ 11引入了委托构造函数:
委托构造函数
如果类本身的名称在成员初始值设定项列表中显示为class-or-identifier,则该列表必须仅由该一个成员初始值设定项组成;这样的构造函数称为委托构造函数,并且由初始化程序列表的唯一成员选择的构造函数是目标构造函数
在这种情况下,将通过重载分辨率选择目标构造函数并首先执行它,然后控件返回到委托构造函数并执行其主体。
委托构造函数不能是递归的。
Run Code Online (Sandbox Code Playgroud)class Foo { public: Foo(char x, int y) {} Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char,int) };
请注意,委派构造函数是一个全有或全无的提议。如果一个构造函数委托给另一个构造函数,则不允许调用构造函数在其初始化列表中包含任何其他成员。如果您考虑一次初始化const / reference成员,并且只初始化一次,则这很有意义。