Is it legal to have 2 header files for the same class in c++?

642 views Asked by At

In a project I read, there are two header files and two declarations for the same class. One is used by programs that use this library, serving as an interface. Another is used by the library itself.The interface header file is simpler. It doesn't contain private members and has less methods. Even methods that appear in both files may not appear in the same order. I wonder if it is legal to have 2 header files for the same class? If it is not, what are the possible consequences?

1

There are 1 answers

0
Christophe On

In short

This is not legal at all. Depending of what's in the private part that is committed, it might work on some implementations, but it might very well fail at the first change or new release of the compiler. Just don't. There are better ways to achieve the intended objectives.

Some more explanations

Why it's not legal?

It's the One Definition Rule (ODR). It's defined in the standard, in a long section [basic.def.odr]. In summary, it is possible to have multiple definition of the same class in different compilation units (e.g. your code, and the library's code), but only if it's exactly the same definition. This requires that it's exactly the same sequence of tokens that are used for the two definitions, which is clearly not the case if you leave out the private members. (Note that there are additional requirements as well, but the first one is already broken, so I short-circuit).

Why does it work in practice in some cases even if not legal?

It's purely implementation dependent luck. I will not develop this topic, in order not to encourage dangerous behavior.

What alternatives

Just use the same definition of the class everywhere. Private members are private, so what's the risk of leaving them where they were ?

Ok, sometimes the definition of private members would require to disclose also private types, end as a chain reaction, much too much. In this case, you may think of:

  • The simple opaque pointer technique, which uses a pointer to a private implementation class, whose type is declared but that is not defined in the compilation units that do not need to know.
  • The more elaborate bridge pattern, which allows to build class hierarchies for an abstraction, and class hierarchies with the implementation. It can be used in a similar way than the opaque pointer, but would allow for different kind of private implementation classes (it's a complex pattern, and it's an overkill if it's just for hiding private details).