Are class members guaranteed to be contiguous in memory?

It is guaranteed that they appear with increasing addresses in the order declared. This is true in general of data members without intervening access specifiers, so if there are other data members in the class then the only way they could intervene is if there are access specifiers in there.

I don't think it's guaranteed to be safe to modify padding bytes. I don't think it's guaranteed that the implementation won't put "something important" in between data members, although I can't immediately think of anything an implementation would want to put in there. Type information for a strangely-designed accurate-marking GC? Recognizable values to test for buffer overruns?

It's not guaranteed that all-bits-zero represents a null function pointer.

You could deal with the issue of the all-bits-zero representation using something like:

std::fill(&func1, &func4 + 1, (void(*)(void))0);

but that would still leave the issue of padding. You're guaranteed no padding in an array, but not (by the standard) in a class. The ABI used by your implementation might specify struct layout to the degree necessary to ensure that your class above is laid out the same as an array of 4 function pointers.

An alternative is to do the following:

struct function_pointers {
    void (*func1)();
    void (*func2)();
    void (*func3)();
    void (*func4)();
};

class C : private function_pointers
{
public:
    C() : function_pointers() {}
};

The initializer function_pointers() dictates that (since it doesn't have a user-declared constructor) the members of function_pointers are zero-initialized even if the instance of C itself is only default-initialized. function_pointers could be a data member rather than a base class, if you prefer to type a bit more to access func1 etc.

Note that C is now non-POD in C++03. In C++11 C remains standard-layout after this change, but would not be standard-layout if there were any data members defined in C, and it is not a trivial class. So if you were relying on POD/standard/trivial-ness then don't do this. Instead leave the definition of C as it is and use aggregate initialization (C c = {0};) to zero-initialize instances of C.


Do this first.

class C
{
public:
    C() : func1(nullptr), func2(nullptr), func3(nullptr), func4(nullptr)
    { };
private:
    void (*func1)();
    void (*func2)();
    void (*func3)();
    void (*func4)();
};

Never ever use memset on non-trivial objects, particularly on those which are polymorphic (having virtual functions or deriving from base class having virtual methods and so forth). If you do it, you would blow-up the vptr which points to vtable! A disaster!

vptr & vtable are used to implement polymorphic behavior, hence respect those hidden class members.

memset should be used when we talk in terms of bits and bytes, not when we talk about objects.

Respect non-trivial objects, say no to memset :)


NEVER do this in C++ unless you really know what you're doing. This is very error-prone and future maintainers of your code (that might even be you!) possibly won't recognize all the pitfalls present and things will likely go horribly wrong. The C++ way of achieving this is to write a constructor that properly initializes the function pointers to nullptr (if you're using C++11) or 0.