我只是在阅读meyers“更有效的C ++ 35新方法” - 第33项,他建议那里 总是从一个抽象的基类继承,而不是一个具体的。
他声称我不能理解的一个原因是,从一个抽象类继承,多态地处理数组(书中的第3项)不是问题。
有人可以建议那是怎么回事?
此外,我想听听是否真的永远不会让客户端实例化其他派生的类? (例如,他的书中的迈耶斯显示了赋值算子的问题)
请求的代码示例:
CLASS BST {....};
CLASS BlanacedBST :: public BST {....}
void printBSTArray(ostream& s,const BST array [],int Numelements) { for(int i = 0; i< Numelements; i ++) { s<<阵列[I]; } }
BST BSTArray [10]; printBSTArray(BSTArray); //工作正常
BlanacedBST bBSTArray [10]; printBSTArray(bBSTArray); //未定义的行为(因为下标运算符根据BST块大小推进指针)
然后,他补充道,避免从另一个类别(BST)继承的concreate类(BlanacedBST)通常可以避免这个问题 - 我不知道如何。
答案 0 :(得分:2)
虽然我认为避免从非抽象类中继承是一个很好的设计指南,并且应该让你对设计三思而后行,但我绝对不认为它属于“从不这样做”。
我会说,由于切片问题,设计为继承的类中包含数据的类应该隐藏其赋值运算符。
我认为有一种方法可以对那些通常没有想到的类进行分类,我认为这会引起很多混乱。我认为有些类被设计为由值使用,而类被设计为始终被引用使用(意思是通过引用或指针或类似的东西)。
在大多数面向对象语言中,用户定义的类只能通过引用使用,并且有一些特殊的“原始”类型可以由值使用。 C ++的一大优势在于您可以创建可由值使用的用户定义类。这可以带来一些巨大的效率。例如,在Java中,你所有的点(选择一个随机的简单类)都是堆分配的,需要进行垃圾收集,即使它们基本上只有两三个双打并加上一些不错的'最终'支持函数。
因此,旨在通过引用使用的类应禁用赋值,并应认真考虑禁用复制构造,并要求人们为此目的使用“复制此虚拟函数”。请注意,Java类通常没有类似赋值运算符或标准副本构造函数的东西。
设计为value使用的类通常不应具有虚函数,尽管将它们作为继承层次结构的一部分可能非常有用。它们仍然可能相当复杂,因为它们可以包含对被设计为引用的类的对象的引用。
如果需要将引用类视为由值使用,则应使用句柄/主体设计模式或智能指针。 STL容器都设计为由值对象使用,因此这是一个相当常见的问题。
答案 1 :(得分:1)
迈耶斯并没有说你可以毫无问题地创建阵列;他说你尝试创造它会更加困难。编译器会在您尝试初始化时立即抱怨,因为如果它是抽象的,则无法创建基类的对象。