在不破坏旧代码的情况下,将成员添加到现有结构中
Add member to existing struct without breaking legacy code
在我使用的一些遗留代码中有以下定义。
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
类型,那么类的什么用途会被破坏
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;
}
有没有一种安全的方法可以确保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 );
我不是c++0x方面的专家,但我确实知道,随着standard-layout
类的引入,严格的pod
保密性在c++0x
中得到了放松。您的带有构造函数的类不是pod
,但我相信它是standard-layout
,因此可能值得检查编译器与新标准这一方面的兼容性。我认为你遇到的问题已经用c++0x
解决了很多。
我还相信在c++0x中也允许对标准布局类进行花括号初始化。请参阅这篇维基百科文章的Initializer lists
和Uniform initialization
部分。
查找标准布局类的修复应该会给出一个相当好的列表,说明在当前标准中,非pod类型可以破坏什么。例如,对于非pod类型(对齐方式可能不正确(,repret_cast在c++03中是不安全的,但对于标准布局类,在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;
}
}
然后你就可以明确地知道什么时候使用什么,并在需要的时候迁移东西。
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 添加静态constexpr成员是否会更改结构/类的内存映射
- 我可以在 C++ 中将数据成员/变量从其定义之外添加到结构中吗?
- 将私有数据成员添加到野牛生成的类中
- 如何在友元函数中使用静态成员而不添加前缀 [类名]::
- 如何添加依赖于类本身的模板成员变量
- '将成员函数仅添加到类的专用模板
- 如何将任何值转换为对象并使用 boost::p roperty_tree json 添加成员
- 如何为内置类型添加成员功能,例如C 中的整数
- 基于模板参数添加成员函数和成员变量
- 如何使用std::bind向信使系统添加成员回调
- 是否为模板类的某些模板参数添加成员
- 添加成员的声明会导致其隐式初始化
- 具有宏添加成员和影响构造函数
- 如何在添加成员时维护结构的初始化
- 向绑定到Lua的c++类添加成员函数
- 添加成员提升::p tr_vector<>
- 在实现文件中添加成员函数
- 在大解决方案中向类添加成员时发生堆栈溢出错误
- 为第三个库类型添加成员字段