将成员添加到现有结构而不破坏遗留代码

时间:2011-07-19 06:01:34

标签: c++ struct value-initialization

我正在使用的一些遗留代码中有以下定义。

struct VlanData
{
    uint16_t mEtherType;
    uint16_t mVlanId;
};

我想在此结构中添加一个新成员:

struct VlanData
{
    uint16_t mEtherType;
    uint16_t mVlanId;
    uint8_t mVlanPriority; // New member
};

但是,VlanData的使用在遗留代码中相当不一致。

未在施工时初始化:

VlanData myVlans;
myVlans.mEtherType = 0x8100;
myVlans.mVlanId = 100;

初始化值:

VlanData myVlans = { 0x8100, 100 };

我想要做的是提出一种安全的方法来确保遗留代码中的“mVlanPriority”自动设置为0,而无需更新大量代码。

我知道我可以修改遗留代码以对所有成员进行值初始化,如下所示:

VlanData myVlans = {};

但我不想更新所有这些代码。我相信创建这样的默认构造函数会有所帮助:

VlanData()
: mEtherType(0),
  mVlanId(0),
  mVlanPriority(0)
{}

但这也会破坏结构的POD -

所以我想我有几个问题:

  1. 有没有一种安全的方法可以确保遗留代码中的mVlanPriority设置为0而不更新遗留代码?
  2. 如果这不再是POD类型,那么该类的哪些用途会中断?

3 个答案:

答案 0 :(得分:5)

struct VlanData {
    struct P
    {
        uint8_t operator=(uint8_t v) { mVlanPriority = v; }
        uint8_t mVlanPriority; P() { mVlanPriority = 0; };
    };
    uint16_t mEtherType;
    uint16_t mVlanId;
    P mVlanPriority;
 };

定义其他类型的运算符并根据需要添加类型转换函数。

例如:

int main(int argc, char** argv)
{
    VlanData myVlans0 = { };
    VlanData myVlans = { 0x8100, 100 };
    myVlans.mVlanPriority = 10;
}

答案 1 :(得分:1)

  

是否有一种安全的方法可以确保将mVlanPriority设置为0 in   遗留代码而不更新遗留代码?

当前标准中没有标准方法。你必须要有构造函数。

  

如果这不再是POD类型,那么该类会有什么用处呢?

正如@junjanes在评论中提到的那样,在您尝试使用括号初始化成员的地方,您的代码将被破坏。

修改:为了解决您的问题,我建议

struct VlanData
{
  uint16_t mEtherType;
  uint16_t mVlanId;
  uint8_t mVlanPriority; // New member

  VlanData(uint16_t ether, uint16_t id, uint8_t priority = 0) :
           mEtherType(ether), mVlanId(id), mVlanPriority(priority)
  {}
};

现在,您的新变量将初始化为0,您必须执行更少的输入以修复编译错误

更改,

VlanData myVlans = { 0x8100, 100 };

要,

VlanData myVlans( 0x8100, 100 );

答案 2 :(得分:0)

我不是c ++ 0x的专家,但我确实知道严格的pod - ness guarentees在{​​{1}}放宽了,引入了c++0x类。具有构造函数的类不是standard-layout,但我认为它是pod,因此可能值得检查编译器与新标准的这一方面的兼容性。我认为你所遇到的问题已经与standard-layout确定了很多。

我也相信在c ++ 0x中也允许标准布局类的花括号初始化。请参阅this维基百科文章的c++0xInitializer lists部分。

查看标准布局类修复的内容应该给出一个相当不错的列表,列出当前标准中非pod类型的内容。例如,对于非pod类型,reinterpret_cast在c ++ 03中不安全(对齐可能不正确),但对于标准布局类,c ++ 0x是安全的。

简而言之,我认为你的挫折得到了很好的认可,甚至可能在新标准中得到了解决,但我认为不可能用现行的标准来解决这些问题。

我的方法是尝试保留遗留旧代码,然后慢慢迁移到您班级的新版本:

Uniform initialization

然后您明确并清楚何时使用了什么 - 并在需要时迁移内容。