How to make a class final (oversolved)

Just mark the destructor final:
http://ideone.com/qrBDwH

Problem solved.

Well, sort of - my question is, since the destructor has to be virtual in order to be marked final (you get an error otherwise), does this cause virtual function overhead anywhere, or add a vtable?
Last edited on
As you want to always have virtual destructor if your class might be refernced by pointer to base class, you rerely will have to worry about that

In case when you only might want for destructor to be virtual final to prevent inheritance, this is a tricky question. Basically it should generate a vtable and store a pointer to it in class, adding overhead in virtual destructor call. However overhead is minimal and I hope destructor is not the most used function in your class.

I can imagine that if only virtual function is final destructor and your class isn't inherited from other, compiler will deduce that virtualness of destructor does not matter and will generate code as it wasn't virtual.

On a simple test case gcc had generated exactly same assembly code in both virtual and non-virtual case on -O2 (and had generated different code without optimizations). However it is too simple case to be sure.
> does this cause virtual function overhead anywhere

Typically, no.

Just checked it out with g++.
1
2
3
4
5
6
7
8
9
10
struct A
{
    virtual ~A() final ;
    int i = 0 ;
};

void foobar( A* p )
{
    delete p ;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	.file	"test.cc"
	.text
	.p2align 4,,15
	.globl	__Z6foobarP1A
	.def	__Z6foobarP1A;	.scl	2;	.type	32;	.endef
__Z6foobarP1A:
	movl	4(%esp), %ecx
	testl	%ecx, %ecx
	je	L1
	jmp	__ZN1AD0Ev ; jump to A::~A()
	.p2align 4,,7
L1:
	rep ret
	.ident	"GCC: (GNU) 4.9.0 20130901 (experimental)"
	.def	__ZN1AD0Ev;	.scl	2;	.type	32;	.endef


> or add a vtable?

Typically yes. Unless the compiler is fiendishly clever, a vtable (and a pointer to it in the object) is required to support RTTI.
Last edited on
So if RTTI were disabled (-fno-rtti) then in this case it would not generate the vtable? I assume that the compiler is smart, just wanted to be sure since this is a relatively new C++11 feature involved.
AFAIK, at best it can elide the code to initialize the vtable pointer during construction. But to conform to C++ semantics, A is not a pod, A is not a standard-layout-type, A is not trivially-constructible etc.
If it elided everything, A would become a pod.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

struct A
{
    virtual ~A() final {}
    int i ;
};

int main()
{
    std::cout << sizeof(int) << " + " << sizeof(nullptr) << " == "
               << sizeof(A) << '\n' ; // 4 + 4 == 8

    std::cout << std::boolalpha << std::is_pod<A>::value << '\n' // false
               << std::is_standard_layout<A>::value << '\n' // false
               << std::has_trivial_default_constructor<A>::value ; // false
}
Ah, so having a virtual function has semantic effects even if it's final and there are no base classes - that's good to know. Thanks!
Last edited on
The "as-if" rule always applies. It is adequate that the observable behaviour of A was as if it is not a pod, it is not a standard-layout-type, it is not trivially-constructible etc.

Compiler writers tend to invest in optimizing commonly used constructs, and ignore the rarely encountered ones. The extremely rare "polymorphic type with no base class and no derived classes" is not going to engage their attention. The earlier optimization arose from the more general, fairly often encountered in practise, "optimize away the overhead of runtime dispach, if by static analysis, the function to be called can be determined at compile time".

Last edited on
How to make a class final
Just mark the destructor final:

Why not mark the whole class final in the first place?

1
2
3
4
5
6
7
struct A final
{
};

struct B : A
{
};

test.cc:7:12: error: base 'A' is marked 'final'
struct B : A
           ^
test.cc:3:8: note: 'A' declared here
struct A final
       ^
1 error generated.
Ah! I was not aware that a final specifier could be used for the class. One lives and learns!

Thanks, Cubbi.
Wow, thanks Cubbi! I had no idea.
Topic archived. No new replies allowed.