不将“虚拟析构函数放入接口内”根据定义,使它不再是一个接口?
所以这就是我所在的框。我想了解为什么“接口类中的虚拟析构函数”很重要。如果你能坚持到最后,你就会明白为什么这些东西要用引号引起来……我也想让所有词汇都绝对正确。到目前为止,我所处的过程是这样的:
有时你有基类,有时你有从基类继承的派生类。
有时你有基类如果您有一个基指针,它发现自己指向一个派生对象,并且您还希望从该指向派生对象的基指针进行的成员函数调用的行为就像它具有实际上是从派生对象调用的,那么您调用的成员函数最好在基类中声明为 virtual。
接口是任何仅纯虚函数的类。如果从这个接口类派生一个新类并实现所有纯虚函数,那么您最终可以创建派生类的实例。
你永远不可能拥有接口类的实例,但你可以拥有指向接口类的指针的实例。
如果你有一个指向接口类的指针,它实际上指向派生类的一个对象(实际上,我想如果#4是正确的,它总是必须的),并且如果你决定删除通过指针调用该对象,那么如果您的接口类中没有“虚拟析构函数”,则您销毁派生对象的意图将仅作为销毁基对象(即接口类)的调用来执行,并且因为没有虚拟析构函数,事情永远不会到达派生对象的析构函数被实际调用的地步——从而导致内存泄漏。
唷。好的,如果听起来不错,请回答我的问题。像这样在接口中声明一个虚拟析构函数就足够了:
virtual ~iFace();
这对我来说看起来是错误的...所以如果你像这样使析构函数成为纯虚拟的,会发生什么:
virtual ~iFace() = 0;
因为它们只是声明,所以执行这些中的任何一个都算作是“接口类中的虚拟析构函数”?你甚至可以有一个已声明但未定义的析构函数吗?只有当它是纯虚拟的我才会猜测...
无论如何,所以回到标题问题...我真的会尽快...这是金钱镜头...如果你的“虚拟析构函数在里面你的接口类”至少需要一个像这样的空定义:
virtual ~iFace() {};
那么该成员函数不是纯虚拟的(不可能是因为你给了它一个定义),因此你的类不再是一个接口(它不仅仅 包含纯虚拟成员函数)。
这意味着,如果您为接口定义了虚拟析构函数,那么您就不再拥有接口(而只是一些抽象基类)。这只是语言滥用吗?我明白发生了什么事吗?
注意:这一切都来自于问自己“什么是接口?”然后阅读这个问题的答案:如何在 C++ 中声明接口?
希望这不是太长的步行或太短的车程,但我决心完全理解这些概念及其相关词汇。
So here is the box I am in. I want to understand why it is important to have a "virtual destructor inside your interface class". You will see why that stuff is in quotes if you can hang to the end... I also want to get all the vocabulary absolutely correct. Here is where I am at with the process so far:
Sometimes you have base classes, sometimes you have derived classes which inherit from base classes.
If you have a base-pointer that finds itself pointing to a derived-object, and further you want a member function call made from that base-pointer-pointing-to-a-derived-object to behave as if it had actually been called from the derived object, then the member function you call had better be declared virtual in the base class.
An interface is any class with only pure virtual functions. If you derive a new class from this interface class and implement all the pure virtual functions, then you can finally create an instance of the derived class.
You can never have an instance of an interface class, BUT you can have an instance of a pointer-to-interface-class.
In the case where you have a pointer-to-interface-class that actually points to an object of the derived class (actually, I guess it would always have to if #4 is correct), and if you decide to delete that object through your pointer, then if you don't have a "virtual destructor inside your interface class", your intention to destroy the derived object will only be executed as a call to destroy the base object (i.e. the interface class) and since there is no virtual destructor, things won't ever get to the point where the destructor for the derived object is actually called -- thus causing memory leaks.
Phew. Okay, if that sounds right, onto my question. Is it enough just to declare a virtual destructor inside your interface like this:
virtual ~iFace();
That looks wrong to me... so what happens if you make the destructor pure virtual like this:
virtual ~iFace() = 0;
Since they are just declarations, do either of these count for being a "virtual destructor inside your interface class"? Can you even have a declared but un-defined destructor? Only if it is pure virtual I would guess...
Anyway, so getting back to the title question... I really am going as fast as I can... Here is the money shot... If your "virtual destructor inside your interface class" requires at least an empty definition like this:
virtual ~iFace() {};
Then that member function is not pure virtual (can't be because you gave it a definition) and therefore your class is no longer an interface (it does not only contain pure virtual member functions).
This would imply that if you define a virtual destructor for your interface, then you no longer have an interface (but just some abstract base class). Is this just an abuse of language? Do I understand what is going on?
note: All this came from asking myself "What is an interface?" and then reading this question's answers: How do you declare an interface in C++?
Hope that wasn't too long a walk for too short a ride, but I am determined to completely understand these concepts and their associated vocabulary.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
为什么
抽象类
析构函数应该是虚拟的并且有一个定义?在指向的多态基类指针上调用
delete
派生类对象 &基类没有虚拟析构函数会导致未定义行为。因此,您确实需要将多态基类的析构函数声明为
virtual
。一旦你显式声明你的析构函数是虚拟的,你就需要为其提供一个定义。这是因为编译器默认为每个类生成(定义)一个析构函数,但如果您显式声明析构函数,则编译器不会这样做,而是让您为自己的析构函数提供定义。这是有道理的,因为编译器将显式声明视为您想要在析构函数中执行一些重要操作(即使您不需要这样做)的指示,并且它通过强制您提供给您提供这样做的机会的定义。神话1:
C++ 中有一种叫做
接口
的东西。NO
C++ 作为一种语言不提供
接口
您所说的
接口
在C++中被称为抽象类
。抽象类
用于模拟C++中Interface
的行为。什么是抽象类?
根据定义,抽象类应该具有至少一个纯虚函数。
神话2:
抽象类中的所有函数都必须是纯虚函数。
不
抽象类并不要求其中的所有函数都是纯虚函数。如果抽象对象至少具有一个纯虚函数,则无法创建它。不过,正如您正确提到的,您可以创建指向它的指针。
误区3:
纯虚函数不能有定义。
不
纯虚函数有一个定义是完全有效的。
为什么我需要一个带定义的
纯虚函数
?代码胜于雄辩,所以这是一个简单的例子:
警告:未编译的代码仅供演示
Why
Abstract class
destructor should be virtual and have a definition?Calling
delete
on a polymorphic Base class pointer pointing to a Derived class object & the Base class not having a virtual destructor causes an Undefined Behavior.So you do need to declare the destructor of the polymorphic Base class as
virtual
. Once you declare your destructor explicitly virtual, you do need to provide a definition for it. This is because the compiler by default generates(defines) a destructor for every class but if you explicitly declare the destructor then the compiler does not do so and leaves it for you to provide a definition for your own destuctor. It makes sense because the compiler sees explicit declaration as an indication that you want to do some non trivial operations(even if you are not in need of doing so) in the destructor and it provides you the opportunity to do so by forcing you to give the definition.Myth 1:
There is something called an
Interface
in C++.NO
C++ as a language does not provide an
Interface
What you refer to as
Interface
is called anAbstract class
in C++.Abstract Classes
are used to simulate the behavior ofInterface
in C++.What is an Abstract class?
By definition an abstract class should have at least one pure virtual function.
Myth 2:
All functions inside Abstract class need to be pure virtual.
NO
Abstract classes
do not require all functions inside them to be pure virtual. An object of an Abstract cannot be created if it has at least one pure virtual function. Though, as you correctly mentioned you can create pointers to it.Myth 3:
Pure virtual functions cannot have a definition.
NO
It is perfectly valid for Pure virtual functions to have a definition.
Why would I ever need a
Pure virtual function
with definition?Code speaks louder then words, So here is a simple example:
Warning: Uncompiled code only for demonstration
C++ 没有本机接口实体。接口作为常规类实现。
因此,在 C++ 中,使类成为接口的因素并不是具有普遍共识的东西。就我个人而言,我认为如果一个类没有数据成员,没有用户声明的构造函数,并且它的所有函数都是纯虚拟的 - 除了它的析构函数之外 - 并且它的所有基类(如果有的话)也是一个接口接口。如果一个类不太适合所有这些属性,我可能会将其称为“胖”接口(通常不是赞美!)。
如果要通过指向基类(例如“接口”类)的指针删除动态分配的多态类,则基类析构函数必须声明为
虚拟
。这意味着它必须是用户声明的析构函数,而不是隐式声明的非虚拟
析构函数。一旦显式声明析构函数,就必须为其提供实现。 (当您销毁任何派生类的实例时,无论基类析构函数是否声明为纯虚拟、虚拟或非虚拟,都将始终使用基类析构函数。)这纯粹是 C++ 语言实现细节。这并不意味着你的基类不再是一个“接口”,如果你有一个接口类,那么析构函数的实现很可能在任何情况下都是空的 - 你没有成员或基类会员们要担心的事。
如果您的接口至少有一些纯虚函数,那么将析构函数标记为纯函数并没有真正的优点,您的接口类已经是一个抽象类。派生类析构函数在技术上不会覆盖基类析构函数,因此您不需要派生类提供用户声明的析构函数或类似的内容。
将析构函数声明为纯虚拟还会使您无法在类定义中提供内联析构函数的定义,尽管这是一个小细节。
C++ doesn't have a native interface entity. Interfaces are implemented as regular classes.
What makes a class an interface in C++ is, therefore, not something that has universal agreement. Personally I consider a class to be an interface if it has no data members, no user-declared constructors and all of its functions are pure virtual - with the possible exception of its destructor - and all of its base classes, if any, are also interfaces. If a class doesn't quite fit all of these properties I might refer to it as a "fat" interface (generally not a compliment!).
If you want to delete dynamically allocated polymorphic classes through a pointer to a base class (such as an "interface" class) then the base class destructor must be declared
virtual
. This means that it must be a user-declared destructor and not an implicitly declared destructor which would be non-virtual
.Once you declare a destructor explicitly, you must provide an implementation for it. (A base class destructor will always be used when you destroy an instance of any class derived from it whether or not the base class destructor is declared pure virtual, virtual or non-virtual.) This is purely an C++ language implementation detail. It doesn't mean that your base class is any less of an "interface", if you have an interface class then it is very likely that the implementation of the destructor will be empty in any case - you have no members or base classes with members to worry about.
If your interface has at least some pure virtual functions then there is no real merit to marking the destructor as pure, your interface class is already an abstract class. Derived class destructors don't technically override base class destructors so you're not requiring derived classes to provide user-declared destructors or anything like that.
Declaring a destructor as a pure virtual also robs you of the ability to provide the definition of the destructor inline in the class definition, although this is a minor detail.
——C++ 中的概念称为抽象类。抽象类是具有至少一个纯虚函数的类。但它并不要求其所有成员函数都是纯虚拟的。您无法实例化任何抽象类。
-- 相反,你必须为析构函数提供一个定义,即使它是纯虚的,因为析构函数在继承层次结构中总是以自下而上的方式调用。
< em>标准 12.4:
析构函数可以声明为 virtual (10.3) 或 pure virtual (10.4);如果在程序中创建了该类或任何派生类的任何对象,则析构函数应为定义。
示例:
-- The concept in C++ is called abstract class. An abstract class is a class with at least one pure virtual function. It doesn't require that all of its member functions are pure virtual though. You cannot instantiate any abstract class.
-- On the contrary, you must provide a definition for the destructor even if it is pure virtual because destructors are always called in a down-up manner in inheritance hierarchy.
Standard 12.4:
A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined.
Example:
鉴于这一切,一般来说,您的抽象基类已经有一些纯虚拟成员函数,这确保了不可能实例化它,因此通常的做法是定义一个不执行任何操作的内联虚拟析构函数。
Given all this, in general your abstract base class will already have some pure virtual member function which ensure that it won't be possible to instantiate it, so the usual way of doing things is to define an inline virtual destructor that does nothing.