将虚方法放在可复制类型上是不是一个好主意?

Hos*_*ork 18 c++ clone virtual-functions copy object-slicing

看过一些相关的问题,但不是这个问题......

我把课程视为适合几个主要类别,让我们说这四个简单:

  • 值类具有一些数据和一堆操作.可以复制它们并进行有意义的比较以获得相等性(通过预期副本相同==). 这几乎总是缺乏虚拟方法.

  • 唯一的类,其实例具有禁用分配和复制的标识.通常没有operator==这些,因为你将它们作为指针进行比较,而不是作为对象. 这些通常有很多虚方法,因为没有风险,因为你被迫通过指针或引用传递它们.

  • Unique-but-Clonable类禁用复制,但预先设计为支持克隆,如果这是你真正想要的. 它们具有虚拟方法,最重要的是遵循虚拟构造/克隆习语的方法

  • 容器类继承他们持有的任何属性. 这些往往没有虚拟方法...例如参见"为什么STL容器没有虚拟析构函数?" .

无论持有这种非正式的信仰系统,我都尝试过将虚拟方法添加到可复制的东西中.虽然我可能认为如果"有效"会"真的很酷",但它不可避免地会破裂.

这让我想知道是否有人有一个具有虚拟方法并且不禁用复制的类型的实际好例子?

Mat*_* M. 7

我所拥有的唯一反例是要分配堆栈而不是堆分配的类.我用它的一个方案是依赖注入:

class LoggerInterface { public: virtual void log() = 0; };

class FileLogger final: public LoggerInterface { ... };

int main() {
    FileLogger logger("log.txt");

    callMethod(logger, ...);
}
Run Code Online (Sandbox Code Playgroud)

这里的关键点是final关键字,但这意味着复制a FileLogger不会导致对象切片.

但是,它可能只是final变成FileLogger了一个Value类.

注意:我知道,复制记录器似乎很奇怪......


n. *_* m. 6

能够复制多态类没有任何内在错误.问题是能够复制非叶类.对象切片会得到你.

一个好的经验法则永远不会来自具体的阶级.这样,非叶类自动是不可实例化的,因此是不可复制的.但是,为了安全起见,禁止在其中进行分配也不会有什么坏处.

当然,通过虚函数复制对象没有任何问题.这种复制是安全的.

多态类通常不是"价值类",但它确实发生了.std::stringstream浮现在脑海中.它不可复制,但它是可移动的(在C++ 11中)并且移动与关于切片的复制没有区别.

  • 以下是对经验法则的一些支持引用:Herb Sutter:*"不要从具体类派生出来."*(["虚拟性"](http://www.gotw.ca/publications/mill18.htm) ).Scott Meyers:*"将非叶类抽象化."*(更多有效的C++ _,第33项). (3认同)