【问题标题】:clarification of initialization in C++C++中初始化的说明
【发布时间】:2015-05-01 14:55:53
【问题描述】:

我真的对以下示例感到困惑:

#include <iostream>
class C {
    public:
    int a,b;
};
int main() {
    C c{3,6};
    std::cout<<c.a<<'\n';
    std::cout<<c.b<<'\n';
    return 0;
}

它工作正常并给出了预期的结果。但是如果我像下面这样修改上面的代码。

#include <iostream>
class C {
    int a,b;
    public:
        int get_a(){
            return a;
        }
        int get_b(){
            return b;
        }
};
int main(){
    C c{3,6};
    std::cout<<c.get_a()<<'\n';
    std::cout<<c.get_b()<<'\n';
    return 0;
}

在上面的程序编译中显示了多个错误。为什么在第一个程序中允许统一初始化但在第二个程序中不允许?我哪里错了?

【问题讨论】:

  • 在第二种情况下,类成员变量是private(隐式),不能直接访问。
  • 一般来说:错误应该表明出了什么问题……显示它们通常很有用。但特别是 - 您将数据成员从公共更改为私有。
  • @Mat:如果我添加参数化 ctor,那么它可以正常工作。编译器抱怨没有匹配函数调用'C::C()'

标签: c++ initialization uniform-initialization


【解决方案1】:

默认情况下,c++ class 成员是private,因此无需指定即可获得私有变量。因为您将类型设为私有,所以您不再免费获得聚合初始化,因此您需要为此类编写自己的构造函数:

class C{
    C(int _a, int _b):
    a(_a), b(_b)
    {}
};

您只需要修复 cout 的命名空间,您的代码应该可以正常编译:http://coliru.stacked-crooked.com/a/1d69f4f141d2bcd2

来自标准:

[dcl.init.aggr] aggregate 是一个数组或类,没有用户提供的构造函数,没有用于非静态数据成员的大括号或相等初始化器,没有私有或受保护的非静态数据成员,没有基类,也没有虚函数

在第一个代码中,您只有公共变量,因此代码可以工作,因为您有一个聚合,将变量设为私有是导致问题的原因,因为根据上述定义它不再是聚合。

【讨论】:

    【解决方案2】:

    ab 在您的第二个示例中是 private,因此无法从课堂外访问。

    【讨论】:

      【解决方案3】:

      您需要像第一个示例一样将行 int a,b; 移动到 public: 范围内。

      std::前面还需要cout

      #include <iostream>
      class C {
          public:
              int a,b;     //Make public
              int get_a(){
                  return a;
              }
              int get_b(){
                  return b;
              }
      };
      int main(){
          C c{3,6};
          std::cout<<c.get_a()<<'\n';   //use namespace std::
          std::cout<<c.get_b()<<'\n';   //use namespace std::
          return 0;
      }
      

      【讨论】:

        【解决方案4】:

        在修改后的代码版本中,您移动了 public: 标签,因此 ab 数据成员不再是公开的。因此,它们不能被类外部引用,甚至不能被初始化列表隐式引用。

        【讨论】:

          【解决方案5】:

          第一个代码有效,因为数据成员 ab 是公共的,因此可以从类外部访问它们。但是,在第二个代码中,它们被声明为私有,因此不能从类外部访问它们。要么再次将它们声明为公共,要么使用如下构造函数(如果您仍希望它们为私有):

           C(int x,int y)   // This is a parameterised constructor
              {
                  a=x;
                  b=y;
              }
          

          并将它们初始化为C c(3,6);

          【讨论】:

          • 请注意,您仍然可以在此构造函数中使用C c{3,6} 语法。
          • @shuttle87:给我一个错误:error: in C++98 'c' must be initialized by constructor, not by '{...}'|
          • 在 c++98 中确实需要使用 c(3,6) 语法,在更高版本的 c++0x 及更高版本中,首选方法是使用统一初始化语法。根据编译器/版本,这可能需要允许编译器标志。
          • @shuttle87:哦!感谢您的信息。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-05-31
          • 1970-01-01
          • 1970-01-01
          • 2022-01-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多