我正在读meyers的"More Effective C++ 35 New Ways“--项目33,他建议总是继承抽象基类,而不是具体的基类。
他声称的其中一个原因(我不太明白)是,从抽象类继承,以多态的方式处理数组(本书中的第3项)不是问题。
有人能建议一下这是怎么回事吗?
此外,我想知道永远不让客户端实例化其他派生的类是否真的是一件好事?(例如,meyers在他的书中展示了赋值运算符的一个问题)
请求的代码示例:
类BST {....};
类BlanacedBST::public BST {....}
无效数组(ostream& s,const BST array[],int printBSTArray){ for(int i=0;i < Numelements;i++) {s << arrayi;}}
BST BSTArray10;printBSTArray(BSTArray);//工作正常
BlanacedBST bBSTArray10;printBSTArray(bBSTArray);//未定义的行为(因为下标操作符根据BST块大小前进指针)
然后,他补充说,避免从另一个具体类(BST)继承的concreate类(BlanacedBST)通常可以避免这个问题-我不明白这是如何做到的。
发布于 2009-12-12 23:47:01
虽然我认为避免从非抽象类继承是一个很好的设计指南,应该让你在设计时三思而后行,但我绝对不认为它属于“永远不要做这件事”的范畴。
我要说的是,由于切片问题,被设计为从其中包含数据的类继承的类可能应该隐藏其赋值操作符。
我认为有一种方法来对类进行分类,这是人们通常不会想到的,而且我认为这会造成很多混乱。我认为有一些类被设计成通过值使用,还有一些类被设计成总是通过引用使用(意思是通过引用或指针或类似的东西)。
在大多数面向对象的语言中,用户定义的类只能通过引用使用,并且有一种特殊的“原始”类型可以通过值使用。C++的一大优势是你可以创建用户定义的类,这些类可以通过值来使用。这可以带来一些巨大的效率优势。例如,在Java中,你所有的点(选择一个随机的简单类)都是堆分配的,需要进行垃圾回收,即使它们基本上只是两到三个doubles,再加上一些很好的“最终”支持函数。
因此,被设计为通过引用使用的类应该禁用赋值,并且应该认真考虑禁用复制构造,并要求人们为此使用“复制此”虚拟函数。注意,Java类通常没有任何赋值运算符或标准复制构造函数。
被设计为由值使用的类通常不应该有虚函数,尽管让它们成为继承层次结构的一部分可能非常有用。但是,它们仍然可以相当复杂,因为它们可以包含对被设计为通过引用使用的类的对象的引用。
如果您需要将按引用类视为由值使用,则应使用句柄/主体设计模式或智能指针。STL容器都被设计为由值对象使用,所以这是一个相当常见的问题。
发布于 2009-12-13 00:07:49
Meyer并没有说你可以创建一个没有问题的数组;他说你尝试创建它会更加困难。一旦你试图初始化它,编译器就会报错,因为如果基类是抽象的,你就不能创建它的对象。
https://stackoverflow.com/questions/1893688
复制相似问题