我看过一些相关的问题,但不是这个...
为了简单起见,我将类归入几个主要类别:
==
,副本应该是相等的)。这些类几乎总是缺少虚拟methods.operator==
,因为您将它们作为指针进行比较,而不是作为对象。这些类通常有很多虚方法,因为没有的风险,因为你被强制通过指针类或禁止复制的reference.尽管持有这种非正式的信念系统,但我已经尝试过几次将虚拟方法添加到可复制的东西中。虽然我可能认为这将是“真的很酷,如果它工作”,不可避免地它崩溃了。
这让我想知道,有没有人有一个真正好的类型示例,它具有虚方法并且不禁用复制
发布于 2013-12-01 14:55:40
能够复制多态类本身并没有什么错。问题在于是否能够复制非叶子类。对象切片会让你。
一个好的经验法则是永远不要从一个具体的类派生出来。这样,非叶类就会自动成为不可实例化的,因此是不可复制的。不过,为了安全起见,在它们中禁用赋值并不会有什么坏处。
当然,通过虚拟函数复制对象并没有什么问题。这种复制是安全的。
多态类通常不是“值类”,但它确实发生了。std::stringstream
出现在我的脑海中。它是不可复制的,但它是可移动的(在C++11中),就切片而言,移动与复制没有区别。
发布于 2013-11-05 02:04:30
我所拥有的唯一反例是堆栈分配的类,而不是堆分配的类。我使用它的一种方案是依赖注入:
class LoggerInterface { public: virtual void log() = 0; };
class FileLogger final: public LoggerInterface { ... };
int main() {
FileLogger logger("log.txt");
callMethod(logger, ...);
}
这里的关键点是final
关键字,这意味着复制FileLogger
不会导致对象切片。
然而,这可能只是因为final
将FileLogger
转换成了一个值类。
注意:我知道,复制一个记录器看起来很奇怪...
发布于 2013-12-02 17:33:22
虚拟分派发生在运行时。人们需要它的唯一原因是,直到运行时才能知道对象的实际动态类型。如果您在编写程序时已经知道所需的动态类型,则可以使用不同的非虚拟技术(如模板或非多态继承)来构建代码结构。
需要运行时类型的一个很好的例子是解析I/O消息,或处理事件-任何一种情况,您要么使用某种大的开关表来选择正确的具体类型,要么编写自己的注册和分派系统,基本上重新发明了多态性,或者只是使用虚拟分派。
(让我插入一个警告:许多人滥用虚拟函数来解决不需要它们的问题,因为它们不是动态的。当心,并对你所看到的东西持批评态度。)
说到这里,现在很明显,你的代码将主要处理多态基类,例如在函数接口或容器中。因此,让我们重新表述这个问题:这样的基类应该是可复制的吗?好吧,因为你从来没有实际的,派生最多的基对象(即基类本质上是抽象的),这不是一个真正的问题,也没有必要这样做。您已经提到了“克隆”习惯用法,它是在多态中复制的适当类比。
现在,“克隆”功能必须在每个叶类中实现,并且它必然需要复制叶类。所以,是的,在一个可克隆的层次结构中,每个叶子类都是一个具有虚函数和复制构造函数的类。因为派生类的复制构造函数需要复制它的基对象,所以所有的基对象也需要是可复制的。
所以,现在我相信我们已经将问题归结为两种可能的情况:要么你的类层次结构中的所有东西都是完全不可复制的,要么你的层次结构支持克隆,因此必然它中的每个类都是可复制的。
那么,具有虚函数的类是否应该有一个复制构造函数呢?绝对一点儿没错。(这回答了您最初的问题:当您将您的类集成到一个可克隆的、多态的层次结构中时,您向它添加了虚拟函数。)
您是否应该尝试从基引用复制一份?可能不会。
https://stackoverflow.com/questions/19773793
复制相似问题