为什么一个structclass需要一个虚方法来实现多态?
C++: Why does a structclass need a virtual method in order to be polymorphic?
在这个问题之后,我想知道为什么c++中的structclass必须有一个虚拟方法才能多态。
强制使用虚析构函数是有意义的,但是如果根本没有析构函数,为什么强制使用虚方法呢?
因为c++中多态对象的类型基本上是从指向它的虚函数表的指针确定的,虚函数表。然而,只有当至少有一个虚方法时才会创建虚表。为什么?因为在c++中,你永远不会得到没有明确要求的东西。他们称之为"你不必为你不需要的东西付钱"。不需要多态性?你刚刚保存了一个虚表。
强制使用虚析构函数是有意义的
。要通过虚类的基类手动(通过delete
)析构虚类,需要虚析构函数。(现在,正如我在评论中被提醒的那样,这通常是不需要的:与其使用手动内存管理,不如依赖现代智能指针,它也可以正确地与非虚拟析构函数一起工作。)
因此,任何作为多态基类的类通常都需要虚析构函数或虚函数。
并且由于拥有运行时多态性会增加一个开销(类需要存储一个指向其虚方法表的额外指针),默认情况下除非必要,否则不会添加它:c++的设计哲学是"您只为您需要的东西付费"。让每个类都有一个虚拟方法表将与这一原则相冲突。
因为在标准中是这样定义的。
From 10.3/1 [class.virtual]
虚函数支持动态绑定和面向对象编程。声明或继承虚函数的类称为多态类。
如果使用继承,那么至少有一个虚方法是有意义的。如果您没有任何虚方法,那么您可以使用组合来代替。
多态性是允许你的子类覆盖基类函数的默认行为,所以除非你在基类中有虚方法,否则你不能覆盖基类中的方法。
我想知道为什么c++中的结构类必须有一个虚拟方法才能多态?
因为这就是多态类的含义。
在c++中,运行时多态性是通过虚函数实现的。基类声明了一些虚函数,由许多派生类实现,客户端使用基类静态类型的指针(或引用),可以使它们指向派生类(通常是不同的派生类)的对象,然后通过基类指针调用派生类的实现。这就是实现运行时多态性的方式。由于核心角色是由virtual
函数扮演的,它支持运行时多态,这就是为什么具有虚拟函数的类被称为多态类。
没有任何虚方法,就不需要为类的每个对象维护一个虚指针(缩写为vptr)。虚指针是一种在运行时解析虚方法调用的机制;根据对象的类,它可能指向不同的虚方法表(缩写为vtable),其中包含虚方法的实际地址。
因此,通过检查vtr指向的虚函数表,编译器可以确定对象的类,例如在dynamic_cast
中。没有vvpr的对象不能以这种方式确定其类型,并且不是多态的。
c++的设计理念是"不用为不用的东西买单"。您可能已经知道,virtual
函数会产生一些开销,因为类必须维护指向其实现的指针。实际上,对象包含对函数指针表(称为虚表)的引用。
考虑下面的例子:
class Base
{
public:
virtual f() { /* do something */ }
};
class Derived : public Base
{
public:
virtual f() { /* do something */ }
};
Base* a = new Derived;
a->f(); // calls Derived::f()
注意变量a
指向Derived
对象。当f()
被声明为virtual
时,a
的虚函数表将包含一个指向Derived::f()
的指针,并执行该实现。如果f()
不是virtual
,虚表将为空。所以Base::f()
被执行,因为a
的类型是Base
。
virtual
,则只调用Base
类中的析构函数。如果Derived
类实现RAII,这可能导致内存/资源泄漏。如果一个类要被子类化,它的析构函数应该是virtual
。
在Java等语言中,所有方法都是虚拟的。因此,即使是不打算多态的对象也会消耗用于维护函数指针的内存。换句话说,你被迫为你不使用的东西付费。
类只需要虚方法,以便动态地多态-出于其他人描述的原因。但是,您仍然可以通过模板实现静态多态性。
- 实现一个在集合上迭代的模板函数
- 在用于格式4的arm模拟器中实现功能时的一个问题
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 为什么我们要为avl树实现返回一个指向节点的指针,而不是void函数
- 给定一个指向堆分配内存的指针,智能指针实现如何为其找到合适的释放函数?
- 为什么在排序链表上的这种合并实现总是将两个列表都设置为 NULL,而只有一个应该设置一个列表?
- 如何为位集找到/实现一个好的哈希函数
- C++哈希表中,两个相同的实现,但一个给出错误
- 如何将这两个函数组合成一个实现?
- 类中的数组变量C++导致"was not declared in this scope"实现文件的一个函数中错误,但在构造函数中不会导致错误
- 为什么这个快速排序实现给出了一个奇怪的输出
- C++:实现一个全局常量,其值由用户给出
- C++:实现一个接收lambda作为输入的高阶函数
- std::sort 一个实现了移动构造函数的类
- GMock - 用另一个实现模拟抽象类
- 有没有办法(C++)创建一个实现某些功能的模板类?
- 创建一个实现选项卡并可用作 QMainWindow 中的"central widget"的类
- 说出一个实现STL兼容序列容器的好指南)
- 一个C++实现的隐马尔可夫模型林安装错误
- 一个实现是否允许在同一地址放置两个相同的函数定义