Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I apply the final keyword to a POD (standard-layout) struct in C++11 ? Should I?

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:

  • Whether the compiled code will execute correctly in all situations (especially when the technique is applied in a larger, more complex project),
  • Whether the C++ standards body intends this to be used in this way.
#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;
}
like image 726
rwong Avatar asked Jul 14 '15 05:07

rwong


People also ask

Can we use new keyword with structure?

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.

When struct is used instead of the class keyword will anything change in the program?

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; };

Is there final keyword in CPP?

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.

What does standard layout mean?

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.


1 Answers

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.

like image 165
Potatoswatter Avatar answered Oct 14 '22 08:10

Potatoswatter