【问题标题】:Scoping issues when chaining class constructors链接类构造函数时的范围问题
【发布时间】:2013-05-06 04:31:18
【问题描述】:

为什么链接构造函数时以下不起作用:

#include <iostream>
#include <vector>

class cls {
public:
    cls()           {cls(5);}       // want to resize v to 5
    cls(int n)      {v.resize(n);}
    std::vector<int> v;
};

int main(int argc, const char* argv[]) {
    cls x, y(5);
    std::cout << x.v.size() << std::endl;   // prints 0 <- expected 5
    std::cout << y.v.size();                // prints 5
    return 0;
}

演示:http://ideone.com/30UBzS

我希望两个对象都有大小为 5 的 v。怎么了?

我想这样做的原因是因为编写单独的 cls()cls(n) ctors 会重复很多代码。

【问题讨论】:

  • {cls(5);} 是错字吗?应该是v.resize(5);
  • 这就是我的意思,我希望第二个构造函数来处理它。它希望避免代码重复,因为在我的完整代码中实际上不仅仅是v.resize

标签: c++ class constructor scope


【解决方案1】:

这是你需要的:

class cls
{
public:
       cls()
       :
       v( 5 ){}               // create v that contains 5 elements ( each initialized to 0 ) - note: this is NOT resizing

        explicit cls( const int size )
        :
        v( size ){}
private:       
        std::vector<int> v;
};

当然,如果您需要调整活体对象的大小功能,则需要此线程中已经提到的“调整大小”方法。

【讨论】:

    【解决方案2】:

    cls::cls() 构造函数内部调用cls(5); 并没有按照您的想法执行。它使用在; 销毁的第二个cls 构造函数创建一个临时变量。

    您可以使用 C++11 的委托构造函数来实现您想要的:

    cls() : cls(5) { }
    

    如果您没有支持 C++11 的编译器,您可以将通用初始化提取到另一个函数中,并让两个构造函数都调用它:

    class cls {
    public:
        cls()           { init(5); }
        cls(int n)      { init(n); }
        std::vector<int> v;
    private:
        void init(int n) { v.resize(n); }
    };
    

    【讨论】:

      【解决方案3】:

      你应该改变

      cls()  {cls(5);} 
      

      cls()  {v.resize(5);} 
      

      否则,您将在构造函数中创建新的临时 cls 并忽略它。


      或者如果你想delegate the constructor (C++11) 这样做

      cls() : cls(5)  {} 
      //   ^^   ^
      //        | use cls(int n)
      

      委托构造函数只允许在构造函数的member initialization 列表中。

      【讨论】:

      • 所以我不能像普通函数一样调用cls(n)?如果我想要cls() {dostuff(); cls(5); ...}怎么办?
      • @MiloChen cls(5) 正常创建一个新类。除非它在另一个构造函数的成员初始化列表中。
      【解决方案4】:

      cal(5) 创建了一个完全不同的对象,实际上它是一个临时的意思,该对象将在其封装表达式结束时被销毁。或者由于编译器优化,它可能根本不会被调用。

      但除此之外,构造函数调用只影响临时对象,而不影响调用构造函数的原始对象。

      如果您的目的是缩短代码,您应该创建一个成员函数来执行此操作(假设您的编译器不支持 C++11,在这种情况下您可以简单地使用 Delegating Constructor 特征):

      class cls
      {
          void resize(int n)
          {
              v.resize(n);
          }
      
          public:
              cls()           { resize(5); }
              cls(int n)      { resize(n); }
              std::vector<int> v;
      };
      

      【讨论】:

        猜你喜欢
        • 2012-05-29
        • 2018-12-14
        • 1970-01-01
        • 2020-01-03
        • 1970-01-01
        • 1970-01-01
        • 2011-11-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多