In a C++ project that is full of objects (with proper behaviors) and relatively few of non-object-oriented structs (consisting of only data fields and no methods), I would like to prevent the accidental misuse of these structs, in which one might try to create a class inheriting from it.
According to my understanding, because these "POD" (plain old data) structs do not have a virtual destructor, it is not possible to properly delete a derived class object (if one is allowed to create it) via a pointer of the POD type.
This seems to make a good use case for the C++11 "final" keyword, which marks a class or struct as non-inheritable.
However, I wonder if the "final" keyword causes the struct to become non-POD?
I suspect that the standards documentation may have addressed this issue, but I am not intelligent enough to sift through the very long documentations to find out. Any useful pointers would be welcome.
Note: I am not interested in merely knowing that it passes the compilation of some compiler vendors. Passing compilation do not guarantee:
#include <iostream>
using namespace std;
struct Pod final
{
int a;
int b;
int c;
};
#if 0
class FailsBecauseCannotDeriveFromFinalAnything : public Pod
{
};
#endif
class ContainsSomethingFinalAsMember
{
public:
ContainsSomethingFinalAsMember() : pod() {}
private:
Pod pod;
};
int main()
{
std::cout << std::is_pod < Pod > :: value << std::endl;
return 0;
}
We can instantiate Struct using the new keyword as well as using Pointer Address Operator in Golang as shown in the below example: Example: Here, you can see we are instantiating a Struct using new keyword.
The reality is that this completely up to you and your team, and it'll make literally no difference whatsoever to your program. The following two classes are absolutely equivalent in every way except their name: struct Foo { int x; }; class Bar { public: int x; };
We can also use final in Java to make sure that a class cannot be inherited. Similarly, the latest C++ standard C++ 11 added final. Use of final specifier in C++ 11: Sometimes you don't want to allow derived class to override the base class' virtual function.
Standard-layout types can have user-defined special member functions. In addition, standard layout types have these characteristics: no virtual functions or virtual base classes. all non-static data members have the same access control. all non-static members of class type are standard-layout.
According to my understanding, because these "POD" (plain old data) structs do not have a virtual destructor, it is not possible to properly delete a derived class object (if one is allowed to create it) via a pointer of the POD type.
It's not possible given a raw pointer, but it is possible given a smart pointer object, such as std::shared_ptr
or a std::unique_ptr
with an appropriate deleter.
Since smart pointers were standardized, there are few excuses to continue following the poor practice of using the delete
operator manually. Certainly, classes shouldn't be designed around compatibility with the delete
operator. Each class interface should be designed with its particular uses in mind.
No, it's not a good practice to make every class either final
or polymorphic.
However, I wonder if the "final" keyword causes the struct to become non-POD?
No, it's still POD. The requirements for POD are standard layout (in turn requiring no base class, no access specifiers between members, no virtual anything) and trivial special member functions (copy/move constructor, assignment operator, destructor).
However, the purpose of POD-ness is to allow you to use memcpy
instead of properly constructing objects, which good C++ code would avoid doing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With