我正在使用的一些遗留代码中有以下定义。
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
-
所以我想我有几个问题:
mVlanPriority
设置为0而不更新遗留代码? POD
类型,那么该类的哪些用途会中断?答案 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++0x
和Initializer lists
部分。
查看标准布局类修复的内容应该给出一个相当不错的列表,列出当前标准中非pod类型的内容。例如,对于非pod类型,reinterpret_cast在c ++ 03中不安全(对齐可能不正确),但对于标准布局类,c ++ 0x是安全的。
简而言之,我认为你的挫折得到了很好的认可,甚至可能在新标准中得到了解决,但我认为不可能用现行的标准来解决这些问题。
我的方法是尝试保留遗留旧代码,然后慢慢迁移到您班级的新版本:
Uniform initialization
然后您明确并清楚何时使用了什么 - 并在需要时迁移内容。