问题:我有一个非常大的 POD 变量结构,我需要复制一些字段,而不是其他字段。懒得写一个成员一个成员的复制函数。
解决方法:将可复制的字段移到基数,分配基数。像这样:
struct A
{
int a, b, c;
};
struct B : public A
{
int d, e, f;
};
//And copy:
B x, y;
(A&)x = y; //copies the part of B that is A
现在,这很脏,我知道。我与同事进行了一场生动、热烈的讨论:这个准则、我的能力和我的道德品质。然而,我听到的最严厉的具体指控是“d、e、f 未在拷贝中初始化”。是的,我知道;这就是意图。当然,我在别处初始化它们。
另一项指控是“不安全的类型转换”。但这是对基类的保证安全的类型转换!几乎就像
((A*)&x)->operator=(b);
但不那么冗长。推导是公开的;所以将 B 视为 A 是公平的游戏。据我所知,没有未定义的行为。
所以,我呼吁 SO 的集体智慧。这是对批评的邀请。大家快来试试吧。
编辑:代码段的最后一行可以通过多种方式扩展为攻击性较小的代码。例如:
void Copy(A& to, const A& from)
{
to = from;
}
B x, y;
Copy(x, y);
功能相同。或者像这样:
x.A::operator=(y);
EDIT2:除了我,没有维护程序员。它来自一个爱好项目。所以不要再可怜那个可怜的灵魂了。
最佳答案
这完全取决于上下文以及这里的哪一部分被认为是“脏”的。
首先,“切片复制”技巧在技术上是合法的。形式上,它并不是真正的“hack”。您还可以通过使用赋值运算符的限定名称来引用 A
x.A::operator =(y); // same as `(A&) x = y` in your case
它开始看起来很眼熟,不是吗?是的,如果您必须在派生类中实现赋值运算符,如果您突然决定手动执行,这正是您要做的
B& B::operator =(const B& rhs)
{
A::operator =(rhs); // or `this->A::operator =(rhs)`
// B-specific part goes here
}
A::operator =(rhs);
部分与上面的“切片复制”技巧完全相同,但是在这种情况下,它用于不同的上下文。当然,没有人会因为后一种使用而责备您,因为这是通常的做法,也是应该的做法。因此,技巧的具体应用的“肮脏程度”再次取决于上下文。作为派生赋值运算符实现的一个组成部分,它非常好,但在您的情况下“单独”使用时,它可能看起来非常有问题。
但是,其次也是更重要的是,在您的情况下我所说的“脏”并不是使用“切片复制”本身的技巧。根据您在问题中的描述,看起来您实际上将数据结构分为两类(A
和 B
)特别是能够使用上述技巧。 这 在这种情况下我称之为“脏”。不是“切片复制”技巧本身,而是使用继承来实现“切片复制”的唯一目的。如果您这样做只是为了避免手动编写赋值运算符,那就是公然懒惰的一个例子。这就是这里的“脏”。我不建议将继承用于这种纯粹的功利目的。
关于c++ - 强制转换为基础引用并进行复制是一种肮脏的黑客行为,但它究竟有什么肮脏之处呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2073341/