c++ - 强制转换为基础引用并进行复制是一种肮脏的黑客行为,但它究竟有什么肮脏之处呢?

标签 c++ coding-style

问题:我有一个非常大的 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); 部分与上面的“切片复制”技巧完全相同,但是在这种情况下,它用于不同的上下文。当然,没有人会因为后一种使用而责备您,因为这是通常的做法,也是应该的做法。因此,技巧的具体应用的“肮脏程度”再次取决于上下文。作为派生赋值运算符实现的一个组成部分,它非常好,但在您的情况下“单独”使用时,它可能看起来非常有问题。

但是,其次也是更重要的是,在您的情况下我所说的“脏”并不是使用“切片复制”本身的技巧。根据您在问题中的描述,看起来您实际上将数据结构分为两类(AB)特别是能够使用上述技巧。 在这种情况下我称之为“脏”。不是“切片复制”技巧本身,而是使用继承来实现“切片复制”的唯一目的。如果您这样做只是为了避免手动编写赋值运算符,那就是公然懒惰的一个例子。这就是这里的“脏”。我不建议将继承用于这种纯粹的功利目的。

关于c++ - 强制转换为基础引用并进行复制是一种肮脏的黑客行为,但它究竟有什么肮脏之处呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2073341/

相关文章:

c++ - 将数组传递给 C++ 中的函数? [彩票号码]

coding-style - 我们应该用什么指标来判断代码质量?

ios - 使用 Setter 和 Getter 方法与直接操作相比的好处

c++ - 多维数组初始化

c++ - 实现COM接口(interface) C++/VC++ 6.0/MFC

C++17 和静态临时生命周期的引用扩展

c++ - 你喜欢在哪里拆分长线?

objective-c - 在 Obj-C 方法声明中不放置任何空格的约定是如何产生的?

android - 如何在组装字符串时为 TextView 生成样式文本?

c++ - 判断一个矩阵是上三角矩阵、下三角矩阵还是对角矩阵