【问题标题】:C++ non-copyable classes and multiple inheritance, pure abstract classesC++ 不可复制类和多重继承,纯抽象类
【发布时间】:2012-08-04 14:32:18
【问题描述】:

我们可能同意默认复制构造在 C++ 中大部分时间都很糟糕,因此最好使用 C++11 =delete 或像 boost::noncopyable 这样的不可复制类显式禁用它。

问题是,当我们使用多重继承或公共抽象类时,在高级场景中会发生什么?

//Class uncopyable
class uncopyable {...};

//Interface1
class IInterface1 : private uncopyable
{
public:
 IInterface1(...)
 virtual ~IInterface1(...) = 0;
};

//Interface2
class IInterface2 : private uncopyable
{
public:
 IInterface2(...)
 virtual ~IInterface2(...) = 0;
};

//Fancy implementation
//FImpl
class FImpl : public IInterface1, public IInterface2, private : uncopyable
{
public:
 FImpl(...) {...}
 ~FImpl(...) {...};
};
  • 让每个接口都不可复制是一种好习惯吗(似乎 是,为了避免切片)?
  • 将不可复制添加到 每个派生类(显式保护,但会导致多个 继承和钻石问题?)

【问题讨论】:

  • 您的界面看起来根本不像界面。它们定义了构造函数,并且没有纯虚方法(只有某种看起来像违反语法的析构函数)。
  • ~IInterface1(...) = 0 只是语法错误。而且你不想让析构函数成为纯虚拟的。
  • 好的,已修复。使用伪代码,而不是真正的代码。
  • 大多数时候,默认的复制结构还不错。在少数情况下是这样。以这种方式开始你的问题对讨论没有帮助。
  • @Coder:Google 指南不是通用的,它们似乎是为 Google 团队优化的(我想这包括比 C++ 更多的 Java 专业知识)。三法则说,只有当你定义一个自定义赋值运算符或析构函数时,默认的复制构造函数才不好,这不是大多数类。

标签: c++ interface multiple-inheritance


【解决方案1】:

不,让界面不可复制不是一个好主意。例如,这可以防止克隆。

不,在每个派生类中从不可复制派生不是一个好主意,因为它只是多余的。

然而,为了特别是阻止 Visual C++ 发出愚蠢的警告,最好在每个应该是不可复制的类中声明一个复制构造函数和复制赋值运算符。

【讨论】:

  • 什么是克隆?据我所知,IInterface1 *ptr = new FImpl();IInterface1 instA = *ptr; 之类的代码是错误的?
  • @Coder:检查FAQ 通常是个好主意
  • 好的,很高兴知道这种方法存在,以前从未听说过。但是,我通常会尽量避免克隆,因为这通常意味着深拷贝、临界区锁、非平凡的复制构造函数(如何复制锁定的互斥体或处理 GDI 画笔?)等等。我通常尽可能使用对 const 的引用。
【解决方案2】:

纯虚拟(接口)类不需要为使用接口而强制执行内存管理。纯虚拟接口的实现应确定它们自己的内存管理要求(如复制和分配)。

也就是说,值语义允许实现完全避免这种情况。值类(可复制、可分配等)更易于推理和使用。 C++ 库中的所有类都是值类。为自己管理内存的值类的一个很好的例子是古老的字符串类。矢量也是一个很好的例子。这些类具有复杂的内部内存管理要求,但是,作为这些类的用户,我不必关心类的这方面。我可以专注于如何使用课程。

我喜欢C++ Now 中的presentation,它展示了多态性也是一个实现细节。这包括客户端实现可以参与多态性的类而不需要接口类(或任何基类)的能力。

【讨论】:

  • 但是字符串和向量是不能派生其他类的类。
猜你喜欢
  • 2019-04-30
  • 2016-11-05
  • 2014-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多