12

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

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-ness。

所以我想我有几个问题:

  1. 有没有一种安全的方法可以确保mVlanPriority在旧代码中将其设置为 0 而无需更新旧代码?
  2. 如果这不再是一种POD类型,该类的什么用途会中断?
4

3 回答 3

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;
}
于 2011-07-19T06:50:19.097 回答
1

有没有一种安全的方法可以确保在旧代码中将 mVlanPriority 设置为 0 而无需更新旧代码?

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

如果不再是 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 );
于 2011-07-19T06:26:32.477 回答
0

我不是 c++0x 方面的专家,但我知道严格的pod保证在 中放松了c++0x,引入了一个standard-layout类。您的带有构造函数的类不是pod,但我相信它是standard-layout,因此可能值得检查您的编译器与新标准的这一方面的兼容性。我认为您遇到的问题已经解决了很多c++0x

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

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

简而言之,我认为您的挫败感得到了很好的认可,甚至可能在新标准中得到解决,但我认为用当前标准不可能解决所有问题。

我的方法是尝试保持遗留代码不变,然后慢慢迁移到你的类的新版本:

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

  vlanData 
  convert_VlanData( ::VlanData const& v)
  {
     VlanData v2 = {v.mEtherType,v.mVlanId, 0};
     return v2;
  }
}

然后你就清楚地知道何时使用什么 - 并在需要时迁移东西。

于 2011-07-19T06:37:58.777 回答