views:

85

answers:

4

Hi,

I am wondering what is produced by the compiler when using non-virtual derivation:

template< unsigned int D >
class Point
{
     int[D];
    // No virtual function
    // ...
};
class Point2 : public Point<2> {};
class Point3 : public Point<3> {};

Does the derivation here only imply compile-time checks? Or is there some other overhead?

I noticed my compiler produces equally sized objects when using Point2 or directly Point<2>. I deduce the derivation did not incur a vtable, and, as a consequence, no virtual call will ever be made.

Am I missing something?


Context

I want to provide a couple of predefined specializations of a given class template. I started with typedefs:

template< unsigned int D >
class Point
{
     int[D];
};
typedef Point<2> Point2;
typedef Point<3> Point3;

Alas, this prevents clients to use "simple" forward declarations:

// No #include <Point.h>
class Point2;    // 'Point2': redefinition; different basic types
class Point3;    // 'Point3': redefinition; different basic types

It is then mandatory to write this rather unintuitive piece of code:

// No #include <Point.h>
template< unsigned int > class Point;
typedef Point<2> Point2;
typedef Point<3> Point3;

This is why I discarded typedefs and used non-virtual derivation. Still, I am wondering what are all the implications.

(Another strategy would be to write the forward declaration once in a dedicated header file, à la #include <iosfwd>.)

A: 

I don't really see what the problem is with using typedefs here. This is the sort of thing that typedef was intended for. I believe that there are a few restrictions when working in namespaces, but it doesn't look like you're doing that here. It's quite common to see something like this:

General.h

#include <map>
#include <string>

class MyObj1;
class MyObj2;

typedef map< string, MyObj1 > MyObj1Map;
typedef map< string, MyObj2 > MyObj2Map;

You can then include that in your source code, though you'll have to remember to include the definition of MyObj1 and MyObj2 where the compiler will need to know the size (i.e other than references and pointers in declarations.)

Robin Welch
@Julien L.: Just picked up on your comment that you're trying to forward-declare a typedef of a class template, so the above probable does not apply. Apologies.
Robin Welch
A: 

I always go with the forward declaration (the typedef one), because of the following reasons;

  1. Inheritance is an alternative to generics.
yadab
I'm sorry, but I have no idea what you're trying to say.
sbi
edited. I have not seen your last comment.
yadab
I am not asking whether you prefer typedefs or derivation, I am asking what the overhead of deriving is (when no virtual function is implied) -- thanks anyway
Julien L.
You are right! I made that mistake :-). Anyway it is going to be same in terms of overhead.
yadab
@Julien: Are you talking of runtime overhead/performance? Derivation, absent of virtual functions, doesn't come with a principle overhead. If the constructors are inlined, I don't think there's a performance difference. Anyway, first strife to write code that's as readable as possible. If then you find (through measurements) that a specific piece of code is to slow, you can fiddle with that.
sbi
@sbi: Yes that is the kind of answer I am expecting. I realize my question is not clear, I will edit it. I know I must strive for code that is as readable as possible -- this is the point of my problem: "how to craft my class template in order to allow clients to forward declare it the simple way?" Then, I was questioning my derivation-based solution.
Julien L.
A: 

The problem with inheritance is that you have to redefine the constructors.

The standard solution (I don't see why you don't want it) is a dedicated header:

// File PointFwd.h
#ifndef POINT_FWD_H
#define POINT_FWD_H 1

template <unsigned> class Point;

typedef Point<2> Point2;
typedef Point<3> Point3;

#endif

Your clients only have to include "PointFwd.h" to forward declare what they want.

Alexandre C.
That is not my question
Julien L.
@Julien: "Am I missing something?" => "The problem with inheritance is that you have to redefine the constructors".
Alexandre C.
+1  A: 

Ok, looks like no one have so far given you an actual answer to your question:

No, there is no overhead to non-virtual derivation. The compiler doesn't have to create a vtable, there are no virtual function calls, and all is well. It is typically implemented simply by placing an instance of the base class at the beginning of the derived class, so that a pointer to the derived class can be treated as a pointer to the base class as well. And then everything just works.

Of course, constructor calls have to be forwarded, but they will usually get inlined, eliminating that overhead as well.

However, if you use multiple base classes, it may introduce a tiny bit of overhead (depending on how the compiler implements it). Probably not much (the this pointer has to be adjusted from time to time), but theoretically, it is there.

jalf