C ++初始化对象的非静态成员数组

Posted

技术标签:

【中文标题】C ++初始化对象的非静态成员数组【英文标题】:C++ Initializing non-static member array of objects 【发布时间】:2018-07-19 11:40:23 【问题描述】:

我正在尝试在不使用 STL 的情况下初始化类的私有成员数组(因为我正在使用的 Arduino 微控制器平台不支持它)。这意味着没有std::arraystd::initializer_list 等。

以下使用 gcc 5.4.0 和 avr-gcc 4.9.2 正确编译,但 that seems to be a bug。 Clang 抛出一个错误,说 error: array initializer must be an initializer list(如预期的那样)。

代码

#include <iostream>
#define PRINTFN() std::cout << __PRETTY_FUNCTION__ << std::endl

class Object 
  public:
    Object(int number) : number(number)  PRINTFN(); 
    Object(const Object &o) : number(o.number)  PRINTFN(); 
    void print()  std::cout << "The number is " << number << std::endl; 

  private:
    const int number;
;

template <size_t N>
class ManyObjects 
  public:
    ManyObjects(const Object(&objects)[N]) : objects(objects) 
    void print() 
    for (Object &object : objects)
        object.print();
    

  private:
    Object objects[N];
;

int main() 
    ManyObjects<3> many = 1, 2, 3;
    many.print();

输出

Object::Object(int)
Object::Object(int)
Object::Object(int)
Object::Object(const Object&)
Object::Object(const Object&)
Object::Object(const Object&)
The number is 1
The number is 2
The number is 3

初始化objects 的正确方法是什么?还是在给定的约束下是不可能的?

【问题讨论】:

你允许 Object 有赋值运算符吗? @UmNyobe,当然,如果需要的话。 你不能使用::boost::array或者自编码数组包装器吗? 【参考方案1】:

您可以使用可变参数模板:

ManyObjects 类中:

template <typename... _Args>
ManyObjects(_Args&&... arguments) :
    objects  arguments... 


更多here

【讨论】:

这确实有效,但它的可读性较差,对最终用户不太友好(Arduino 平台针对初学者),因为它不会将列表的参数与任何其他参数分开到ManyObjects 构造函数。我想我可以用我原来的类包装存储对象的类,但我并不完全相信。 @tttapa, template &lt;typename... _Args&gt; ManyObjects (int arg1, char arg2, _Args&amp;&amp;... arguments) - 如果你想向 ManyObjects 构造函数添加一些其他参数。 注意可变参数模板构造函数,因为ManyObjects(ManyObjects&amp;) 将匹配模板而不是复制构造函数。【参考方案2】:

是的,可变参数模板可以工作,但有点棘手:

template <size_t N>
class ManyObjects 
  public:
    template<typename T, typename ...Args>
    ManyObjects(const T& x, Args&&... args) : objectsx, args...

  private:
    Object objects[N];
;

int main() 
    ManyObjects<3> many1, 2, 3;
    ManyObjects<3> copymanymany;
    copymany.print();

对于任何固定的 N 都可以解释为:

template <size_t N=3>
class ManyObjects 
  public:
        ManyObjects(int x, int y, int z) : objectsx, y, z 
...
;

这里有什么:

    由于构造函数Object(int)的定义,无法默认初始化对象 对象赋值运算符被隐式删除,因为 number 是 const 因此,任何数组Object arr[N] 都必须使用聚合初始化显式初始化。 我想到的唯一方法是通过可变参数模板执行扩展初始化。

    为了防止匹配复制构造函数,您可以在参数包之外指定第一个参数。您松开了大小 0 的构造,可以通过模板特化来启用它。

     ManyObjects<0> noneof;
     noneof.print();
    

【讨论】:

注意可变参数模板构造函数,因为ManyObjects(ManyObjects&amp;) 将匹配模板而不是复制构造函数。 如何定义复制构造函数? 事实上,模板可变参数构造函数应该是 SFINAE 以排除与复制/移动构造函数匹配的签名:检查大小和第一个参数类型。【参考方案3】:

我最终听从了 VTT 的建议,并创建了自己的数组包装器。

如果有我需要注意的事情或可能的错误等,我很乐意听到一些反馈。

#include <iostream>

class Object 
public:
  Object(int number) : numbernumber 
  void print()  std::cout << "The number is " << number << std::endl; 

private:
  const int number;
;

// -------------------------------------------------------------------------- //

template <class T, size_t N> class ArrayWrapper 
public:
    T &operator[](size_t index)  return data[index]; 
    const T &operator[](size_t index) const  return data[index]; 
    T *begin()  return &data[0]; 
    const T *begin() const  return &data[0]; 
    T *end()  return &data[N]; 
    const T *end() const  return &data[N]; 

  T data[N];
;

// -------------------------------------------------------------------------- //

template <size_t N> class ManyObjects 
public:
  ManyObjects(const ArrayWrapper<Object, N> &objects, const char *name)
      : objectsobjects, namename 
  void print() 
    std::cout << name << std::endl;
    for (auto &object : objects)
      object.print();
  

private:
  ArrayWrapper<Object, N> objects;
  const char *name;
;

// -------------------------------------------------------------------------- //

int main() 
    ManyObjects<3> many = 1, 2, 3, "Many";
    many.print();

【讨论】:

以上是关于C ++初始化对象的非静态成员数组的主要内容,如果未能解决你的问题,请参考以下文章

C++面向对象-static、const

如何使用代码初始化静态成员字符数组

C++中静态成员变量(不支持在类定义中初始化不是常量的静态数据成员)

C++静态结构体数据成员的初始化

C ++中的静态构造函数?我需要初始化私有静态对象

C++类和对象下