【问题标题】:Array of constant size, known at compile time.. but in the derived classes only恒定大小的数组,在编译时已知..但仅在派生类中
【发布时间】:2014-09-11 00:23:27
【问题描述】:

我有这些课程 AB 等等..

class A : public O
{
    static const int _nbItems = 3;
    ...
};

class B : public O
{
    static const int _nbItems_mine_mine = 7800;
    ...
};

...

它们都继承自 abstract 父类 O,它知道如何管理 Items 集合,并且不会让孩子们玩弄它随心所欲..

class O
{
private:

    // The kids won't be able to access this structure directly for it is carefully updated
    Item _items[size];        

    // (I mean.. *truly*, look :)
    void update() // called by the clock
    {
       for(int i(0); i < size; ++i) /* things involving */ _items[i] /*, its environment etc.*/
    };

protected:

    // They may set their items this way only:
    void setItemNo(int id, BuildInformation const& buildInfo)
    {
        /* 
         * check whether or not the item has already been added..
         * perform everything that must be done to welcome a new item..
         * well.. 'so many things the kids do not need to be aware of.
         */

        // and then:
        _items[id] = Item(buildInfo);

    };

   // .. retrieve information about the current state of their items this way only:
   SomeInformation getItemState(int id) const {return _items[id].currentState();};

   // .. and eventually change some of their properties this way only:
   void setItemProperty(int id, Property const& newProperty)
   {
     /* checks, updates, eventual repercussions on other items and the environment */
     _items[id].setProperty(newProperty);
   };
};

我可以使用什么作为O::_items 的结构,以获取所有存储在堆栈 上的Items?这应该是可能的,因为它的大小最终在编译时就知道了,不是吗?

换一种说法:我怎样才能让*nbItems* 的信息以一种让编译器知道它们仍然是文字常量的方式到达O::size,即使在O 中还没有定义?


PS:在编写O 时,我显然不知道它有一天可能拥有的所有可能的派生类。

【问题讨论】:

  • 有什么理由O 不能是在size 上参数化的模板类吗?
  • O 设为模板。 template&lt;size_t size&gt; class O { Item _item[size]; } ,那么你的派生类可以派生自O&lt;3&gt;O&lt;7800&gt;
  • @CharlesBailey:哦,也许不是!让我进一步考虑这个.. :)

标签: c++ arrays inheritance literals


【解决方案1】:

你可以有一个没有数组的基类O

class O
{
    virtual size_t size() const = 0;
    virtual Item * data() const = 0;

    void update()
    { 
        for (Item * p = data(), * e = p + size(); p != e; ++p)
        {
            // use *p
        }
    }

public:
    virtual ~O() {}
};

然后是中间派生类:

template <size_t N> class OWithArray : public O
{
public:
    static size_t const nItems = N;
private:
    Item items[N];
    virtual size_t size() const { return nItems; }
    virtual Item * data() const { return items; }
};

然后让所有实际派生类都从中间类派生:

class A : public OWithArray<3>
{
    // ...
};

【讨论】:

  • 很好,为什么不直接将O 作为 T.C 和 Charles Bailey 建议的模板?
  • @Iago-lito:好吧,您在抽象类中说过O(尽管在您的示例中不是)。如果没有更完整的细节,您是否需要将 O 作为一个实际的类而不是类模板并不明显。
  • @Iago-lito 因为如果你直接将O 设为模板,那么O&lt;3&gt;O&lt;7800&gt; 是不同的类型,所以AB 不会有共同的基础班级。这为它们提供了一个通用的基类。
  • @CharlesBailey:是的,O 确实有虚拟方法,但 sn-p 实际上很长。
  • @T.C.:晶莹剔透。其实在实际项目中,已经有一个中间类,我觉得可以这样改造。
【解决方案2】:
class O {
  private:
     Item* items;
     unsigned int number_of_items

  protected:
     O (Item* itemsstorage, unsigned int n_items)
     : items (itemsstorage), number_of_items (n_items) { ... }

  // you'll probably need something like the following
  // make it private rather than using "= delete" prior to C++11
     O & operator = (const O &) = delete;
     O (const O &) = delete;
     O (O &&) = delete;

  public:
     virtual ~O () { }
}

class A : public O {
  private:
     enum { howManyItems = 3 };
     Item allMyItems [howManyItems];

  public:
     A () : O (allMyItems, howManyItems) { }
}

或模板化A 使其更灵活:

template<unsigned int N>
class A : public O {
  private:
     Item allMyItems [N];

  public:
     A () : O (allMyItems, N) { }
}

请注意,如果您将A 的多态性视为O 的,您确实需要类O 中的虚拟析构函数(意味着:除非您绝对是100,否则您肯定会这样做% 确定你不会)!!!!

【讨论】:

  • 您还需要为此提供赋值运算符。
  • 我猜你需要防止复制和移动并分配O's
  • 是的,但这样一来,A 仍然可以用它的Items 做任何它想做的事情,不是吗?没有什么能阻止它自己调用allMyItems[0].setProperty("fancyOne") 并搞砸整个过程?
  • 啊,“孩子”是指派生类。通过将我的A 设置为OwithArray 并从OwithArray 派生您的A,将该方法与其他答案相结合。
  • 我想现在就是这样。谢谢! ^ ^
猜你喜欢
  • 2018-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-23
  • 1970-01-01
  • 2014-08-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多