我可以从另一个构造函数(做构造函数链)在C ++中调用一个构造函数?
作为一个C#开发人员,我习惯于通过构造函数来运行:
class Test { public Test() { DoSomething(); } public Test(int count) : this() { DoSomethingWithCount(count); } public Test(int count, string name) : this(count) { DoSomethingWithName(name); } }
有没有办法在C ++中做到这一点?
我试着调用类名称并使用“this”关键字,但都失败了。
C ++ 11:是的!
C ++ 11及以上版本具有相同的function(称为委托构造函数 )。
语法与C#略有不同:
class Foo { public: Foo(char x, int y) {} Foo(int y) : Foo('a', y) {} };
C ++ 03:没有
不幸的是,在C ++ 03中没有办法做到这一点,但有两种方法来模拟这个:
-
您可以通过默认参数组合两个(或更多)构造函数:
class Foo { public: Foo(char x, int y=0); // combines two constructors (char) and (char, int) ... };
-
使用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) { ... }
请参阅C ++ FAQ条目以供参考。
不,您不能在C ++ 03中调用另一个构造函数(称为委托构造函数)。
这改变了C ++ 11(又名C ++ 0x),它增加了对以下语法的支持:
(以维基百科为例)
class SomeType { int number; public: SomeType(int newNumber) : number(newNumber) {} SomeType() : SomeType(42) {} };
我相信你可以从构造函数调用构造函数。 它会编译并运行。 我最近看到有人这样做,它在Windows和Linux上运行。
它只是不做你想要的。 内部构造函数将构造一个临时的本地对象,一旦外部构造函数返回就会被删除。 他们将不得不是不同的构造函数,否则你会创build一个recursion调用。
参考: https : //isocpp.org/wiki/faq/ctors#init-methods
值得指出的是,您可以在构造函数中调用父类的构造函数,例如:
class A{ .... }; class B: public A { B() : A() { ... do more stuff... } };
但是,不,你不能调用同一个类的另一个构造函数。
在C ++ 11中 , 构造函数可以调用另一个构造函数重载 :
class Foo { int d; public: Foo (int i) : d(i) {} Foo () : Foo(42) {} //New to C++11 };
另外,成员也可以像这样初始化。
class Foo { int d = 5; public: Foo (int i) : d(i) {} };
这应该消除创build初始化帮助方法的需要。 而且仍然build议不要在构造函数或析构函数中调用任何虚函数,以避免使用任何可能未被初始化的成员。
如果你想成为邪恶的,你可以使用就地“新”运营商:
class Foo() { Foo() { /* default constructor deliciousness */ } Foo(Bar myParam) { new (this) Foo(); /* bar your param all night long */ } };
似乎为我工作。
编辑
正如@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 */ } };
看起来不那么优雅,当然。 @ JohnIdol的解决scheme好多了。
不,在C ++中,你不能从构造函数中调用构造函数。 正如沃伦指出的那样,你可以做的是:
- 重载构造函数,使用不同的签名
- 使用参数的默认值,使“更简单”的版本可用
请注意,在第一种情况下,您不能通过调用另一个构造函数来减less代码重复。 你当然可以有一个单独的private / protected方法来完成所有的初始化,并让构造函数主要处理参数处理。
在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); } };
我不知道它是否可以在其他地方使用,我只是在Visual C ++ 2003和2008中testing过。您可能也会这样调用一些构造函数,就像在Java和C#中一样。
PS:坦率地说,我很惊讶,这是没有提到过。
如果我正确理解你的问题,你问是否可以在C ++中调用多个构造函数?
如果那就是你要找的东西,那就不行 – 这是不可能的。
你当然可以有多个构造函数,每个构造函数都有唯一的参数签名,然后在实例化一个新的对象时调用你想要的。
你甚至可以有一个带有默认参数的构造函数。
但是你可能没有多个构造函数,然后分别调用它们中的每一个。
还没有被显示的另一个选项是将你的类拆分为两个,在你的原始类中包装一个轻量级的接口类,以达到你正在寻找的效果:
class Test_Base { public Test_Base() { DoSomething(); } }; class Test : public Test_Base { public Test() : Test_Base() { } public Test(int count) : Test_Base() { DoSomethingWithCount(count); } };
如果你有很多构造函数必须调用他们的“下一级”对象,这可能会变得混乱,但对于less数构造函数来说,它应该是可行的。
我会build议使用一个private friend
方法,实现构造函数的应用程序逻辑,并由各种构造函数调用。 这里是一个例子:
假设我们有一个名为StreamArrayReader
的类, StreamArrayReader
带有一些私有字段:
private: istream * in; // More private fields
我们要定义两个构造函数:
public: StreamArrayReader(istream * in_stream); StreamArrayReader(char * filepath); // More constructors...
第二个简单地使用第一个(当然,我们不想重复前者的实现)。 理想情况下,人们会喜欢做这样的事情:
StreamArrayReader::StreamArrayReader(istream * in_stream){ // Implementation } StreamArrayReader::StreamArrayReader(char * filepath) { ifstream instream; instream.open(filepath); StreamArrayReader(&instream); instream.close(); }
但是,这在C ++中是不允许的。 出于这个原因,我们可以定义一个私有的朋友方法如下,它实现了第一个构造函数应该做的事情:
private: friend void init_stream_array_reader(StreamArrayReader *o, istream * is);
现在这个方法(因为它是一个朋友)可以访问o
的私有字段。 然后,第一个构造函数变成:
StreamArrayReader::StreamArrayReader(istream * is) { init_stream_array_reader(this, is); }
请注意,这不会为新创build的副本创build多个副本。 第二个变成:
StreamArrayReader::StreamArrayReader(char * filepath) { ifstream instream; instream.open(filepath); init_stream_array_reader(this, &instream); instream.close(); }
也就是说, 而不是有一个构造函数调用另一个,都调用一个私人的朋友!
当调用一个构造函数时,它实际上是从堆栈或从堆中分配内存。 所以在另一个构造函数中调用构造函数将创build一个本地副本。 所以我们正在修改另一个对象,而不是我们正在关注的对象。
这种方法可能适用于某些种类的类(当赋值运算符“行得很好”时):
Foo::Foo() { // do what every Foo is needing ... } Foo::Foo(char x) { *this = Foo(); // do the special things for a Foo with char ... }
简单地说,你不能在C ++ 11之前,但是你可以在C ++ 11之后。
会更容易testing,比决定:)试试这个:
#include <iostream> class A { public: A( int a) : m_a(a) { std::cout << "A::Ctor" << std::endl; } ~A() { std::cout << "A::dtor" << std::endl; } public: int m_a; }; class B : public A { public: B( int a, int b) : m_b(b), A(a) {} public: int m_b; }; int main() { B b(9, 6); std::cout << "Test constructor delegation a = " << b.m_a << "; b = " << b.m_b << std::endl; return 0; }
并用98 std:g ++ main.cpp -std = c ++ 98 -o test_1进行编译
你会看见:
A::Ctor Test constructor delegation a = 9; b = 6 A::dtor
所以:)