Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以从C+;中的另一个构造函数(进行构造函数链接)调用构造函数吗+;?_C++_Constructor - Fatal编程技术网

C++ 我可以从C+;中的另一个构造函数(进行构造函数链接)调用构造函数吗+;?

C++ 我可以从C+;中的另一个构造函数(进行构造函数链接)调用构造函数吗+;?,c++,constructor,C++,Constructor,作为一名开发人员,我习惯于使用构造函数: public: StreamArrayReader(istream * in_stream); StreamArrayReader(char * filepath); // More constructors... 类测试{ 公开考试(){ DoSomething(); } 公共测试(int计数):this(){ DoSomethingWithCount(计数); } 公共测试(整数计数,字符串名称):此(计数){ dosome

作为一名开发人员,我习惯于使用构造函数:

public:
    StreamArrayReader(istream * in_stream);
    StreamArrayReader(char * filepath);
    // More constructors...
类测试{
公开考试(){
DoSomething();
}
公共测试(int计数):this(){
DoSomethingWithCount(计数);
}
公共测试(整数计数,字符串名称):此(计数){
dosomethingwhithname(name);
}
}
在C++中有没有办法做到这一点?


<>我尝试调用类名,使用“这个”关键字,但是两个都失败了。

< p>如果我正确地理解了你的问题,你问你是否可以调用C++中的多个构造函数?

如果这就是你想要的,那么不,那是不可能的

当然,您可以有多个构造函数,每个构造函数都具有唯一的参数签名,然后在实例化新对象时调用所需的构造函数

您甚至可以有一个结尾带有默认参数的构造函数


但您可能没有多个构造函数,然后分别调用它们。

< P>不,在C++中,不能从构造函数调用构造函数。正如沃伦指出的,你能做的是:

  • 使用不同的签名重载构造函数
  • 在参数上使用默认值,使“更简单”的版本可用

注意,在第一种情况下,不能通过从一个构造函数调用另一个构造函数来减少代码重复。当然,您可以使用一个单独的私有/受保护方法来完成所有初始化,并让构造函数主要处理参数处理。

不,在C++03中,您不能从一个构造函数调用另一个构造函数(称为委托构造函数)

这在C++11(又名C++0x)中有所改变,它增加了对以下语法的支持:
(示例取自)


C++11:是的

C++11及以后版本具有相同的功能(称为)

语法与C#略有不同:

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++11:是

    C++11及以后版本具有相同的功能(称为)

    语法与C#略有不同:

    C++03:否

    值得指出的是,您可以在构造函数中调用父类的构造函数,例如:

     class A { /* ... */ };
        
        class B : public A
        {
            B() : A()
            {
                // ...
            }
        };
    

    但是,不,在C++03之前不能调用同一类的另一个构造函数。

    我相信可以从构造函数调用构造函数。它将编译并运行。我最近看到有人这样做,它在Windows和Linux上都运行

    它只是做不到你想要的。内部构造函数将构造一个临时本地对象,一旦外部构造函数返回,该对象将被删除。它们也必须是不同的构造函数,否则您将创建一个递归调用


    参考:

    如果你想成为邪恶,你可以使用就地“新建”操作符:

    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 */
        } 
    };
    
    class Foo(){
    私人:
    std::载体材料;
    公众:
    Foo()
    :资料(42)
    {
    /*默认构造函数美味度*/
    }
    Foo(Bar myParam)
    {
    这个->~Foo();
    新的(这个)Foo();
    /*整晚都禁止你的情人*/
    } 
    };
    
    当然,看起来不那么优雅了@JohnIdol的解决方案要好得多。

    在a中:

    此外,成员也可以这样初始化

    class Foo  {
         int d = 5;         
    public:
        Foo  (int i) : d(i) {}
    };
    

    这将消除创建初始化助手方法的需要。仍然建议不要调用构造函数或析构函数中的任何虚拟函数,以避免使用任何可能未初始化的成员。

    另一个尚未显示的选项是将类拆分为两个,围绕原始类包装一个轻量级接口类,以实现您想要的效果:

    class Test_Base {
        public Test_Base() {
            DoSomething();
        }
    };
    
    class Test : public Test_Base {
        public Test() : Test_Base() {
        }
    
        public Test(int count) : Test_Base() {
            DoSomethingWithCount(count);
        }
    };
    

    <>这可能会变得混乱,如果你有很多构造函数必须调用他们的“下一级”,但是对于少数的构造函数,它应该是可行的。

    在VisualC++中,你也可以在构造函数中使用这个符号:-> CordNosi::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中测试过。我想,您也可以像在Java和C#中那样,以这种方式调用几个
    构造函数


    旁白:坦白说,我很惊讶之前没有提到这一点。

    当调用构造函数时,它实际上从堆栈或堆分配内存。因此,在另一个构造函数中调用构造函数会创建本地副本。因此,我们正在修改另一个对象,而不是我们关注的对象。

    我建议使用
    private friend
    方法,该方法实现构造函数的应用程序逻辑,并由各种构造函数调用。以下是一个例子:

    假设我们有一个名为
    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++中不允许这样做。因此,我们可以如下定义一个私有friend方法,它实现了第一个构造函数应该做的事情:

    private:
      friend void init_stream_array_reader(StreamArrayReader *o, istream * is);
    
    现在这个方法(因为它是朋友)可以访问
    o
    的私有字段。然后,第一个构造函数变成:

    StreamArrayReader::StreamArrayReader(istream * is) {
        init_stream_array_reader(this, is);
    }
    
    请注意,这不会为新创建的副本创建多个副本。第二个是:

    StreamArrayReader::StreamArrayReader(char * filepath) {
        ifstream instream;
        instream.open(filepath);
        init_stream_array_reader(this, &instream);
        instream.close();
    }
    
    Tha
    private:
      friend void init_stream_array_reader(StreamArrayReader *o, istream * is);
    
    StreamArrayReader::StreamArrayReader(istream * is) {
        init_stream_array_reader(this, is);
    }
    
    StreamArrayReader::StreamArrayReader(char * filepath) {
        ifstream instream;
        instream.open(filepath);
        init_stream_array_reader(this, &instream);
        instream.close();
    }
    
    Foo::Foo()
    {
        // do what every Foo is needing
        ...
    }
    
    Foo::Foo(char x)
    {
        *this = Foo();
    
        // do the special things for a Foo with char
        ...
    }
    
    #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;
    }
    
    A::Ctor
    Test constructor delegation a = 9; b = 6
    A::dtor
    
    class Foo {
    public: 
      Foo(char x, int y) {}
      Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char,int)
    };