32

I found a mistake in a C++ forward declaration of a class, which was wrongly declared as struct Book instead of class Book. I think Book used to be a struct, got changed to a class but the forward declarations remained.

Book.h:

class Book {
    ...
};

Library.h:

struct Book;

class Library {
    std::vector<Book*> books;
};

There were no compiler warnings and the resulting program seemed to work fine. It made me curious: in theory, can this ever cause a problem? It's just a pointer, yes, but for example, if the class had virtual methods, multiple inheritance, could the pointers be different?

I know the differences between class/struct regarding default public/private but I'm asking specifically about the forward declarations and possible consequences of swapping them.

UPDATE newer versions of Xcode now give this warning when there's a mismatch:

Struct 'Book' was previously declared as a class; this is valid, but may result in linker errors under the Microsoft C++ ABI
Tomas Andrle
  • 13,132
  • 15
  • 75
  • 92

1 Answers1

34

struct and class are completely interchangeable as far as forward declarations are concerned. Even for definitions, they only affect the default access specifier of the objects members, everything else is equivalent. You always define "classes" of objects.

The only place where struct must be used over class, is when forward declaring opaque data for bindings.


Regarding your edit:

I know the differences between class/struct regarding default public/private but I'm asking specifically about the forward declarations and possible consequences of swapping them.

Visual C++ produces warning C4099. It does it, because the name decoration for its functions incorporates the keyword you used. Therefore, programs may fail to link properly. So perfectly standard compliant code may not link when using VC++ (A bonehead move on Microsoft's part, AFAIC).

A discussion of this warning, as well as why it can be ignored if you are disciplined, can be found here

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • Thanks for the answer. For peace of mind and to avoid any compiler quirks and possible future psychopathic maintainers' wrath, I will make all the forward declarations match. – Tomas Andrle Nov 22 '16 at 18:12
  • That behaviour is what I needed for my current task. I need to make forward declaration on a type passed as template parameter or macro parameter but the passed type can be a class or struct. – acegs Oct 30 '18 at 04:34
  • 1
    This can indeed cause linker errors in VC++. See https://stackoverflow.com/questions/33483623/visual-c-2015-linker-error-when-forward-declaring-a-struct-as-class – Andy Borrell May 19 '21 at 18:36