抽象类的目的不是让开发人员创建基类的对象并进行向上转换,据我所知。现在,即使不需要向上转换,我仍然使用它,这是否证明在某种程度上“不利”?更多说明:通常在设计中,您希望基类仅为其派生类提供接口。也就是说,您不希望任何人实际上创建基类的对象,只能将其向上转换以使用其接口。这可通过使该类抽象来实现。通过向上转换,我指的是:
baseClass *obj = new derived();
。baseClass *obj = new derived();
。向上转型对于非多态类可能不利。例如:
class Fruit { ... }; // doesn't contain any virtual method
class Apple : public Fruit { ... };
class Blackberry : public Fruit { ... };
将其向上转换并放置在某个地方。
Fruit *p = new Apple; // oops, information gone
*p
是Apple
还是Blackberry
的实例。
[请注意,对于非多态类,不允许使用dynamic_cast<>
]。
抽象类用于表达一组(子)类共有的概念,但是不合理创建实例。
考虑一个类Animal
。创建该类的实例是没有意义的,因为没有仅仅是动物的东西。有鸭子、狗和大象,它们都是Animal
的子类。通过正式声明Animal
类,您可以捕获所有类型动物的相似之处,并通过将其设为抽象来表达它无法被实例化的特性。
在静态类型语言中,需要进行向上转型以利用多态性。正如@Jigar Joshi在评论中指出的那样,这被称为Liskov替换原则。
编辑:向上转型并不是不利的。事实上,您应该尽可能使用它,使您的代码依赖于超类(接口),而不是基类(实现)。这使得您以后可以在不必更改代码的情况下切换实现。
向上转型是一种技术工具。
像每个工具一样,如果使用不当,它会有危险或者不利之处。只有在特定的编程范式下,才能使代码更加“纯粹”,从而使其具有优势或劣势。
C++并不一定是“纯面向对象”的,也不一定是“纯泛型”的,也不一定是“纯函数式”的。由于C++是一种“实用主义语言”,因此通常不会强制将其适应于“唯一的范式”。
从技术角度来说,唯一可以说的是:
dynamic_cast
(用于向下转型)。static_cast
(向下转型),但没有运行时检查。从所有这些点的一致和不一致使用中得出优缺点。这不仅与向下转换有关。
一个缺点是派生类中引入的新功能明显丢失了:
class A
{
void foo();
}
class B : public A
{
void foo2();
}
A* b = new B;
b->foo2(); //error - no longer visible
我在这里谈论的是非虚函数。
此外,如果您忘记将析构函数设置为虚函数,则可能会在通过指向基对象的指针删除派生对象时出现一些内存泄漏。
但是,所有这些都可以通过良好的架构来避免。
foo2()
是B类
的成员而不是A类
的成员,因此它从未被看到过。一旦你写了一个非虚拟的A::foo2()
,它就会悄悄地出现!(注意:我没有对这个答案进行投票) - iammilind
static_cast<Base*>( pDerived )
是一种*向上转型(upcast)*。这是你想要的吗? - Cheers and hth. - AlfbaseClass *obj = new derived();
。 - Aquarius_Girl