While nearly every current programming language has classes and objects, they have some radically different ideas about how one goes about defining classes.
In strongly-typed languages like C++ and Java, classes are declared. This means compilers (and other tools) have essentially complete information about the class during compilation, which in turn allows for certain classes of errors to be found and various optimizations to be applied. It can also be convenient for developers, in that it’s fairly straightforward to read declarative syntax and understand its meaning.
Macros, such as those implemented by the C preprocessor, provide an interesting balance between the two approaches. The result of the macros is a class declaration, and it’s the declaration that’s available to the compiler. However, the macros can simplify class declarations by providing for generation of those declarations when the preprocessor executes. This is frequently used, for example, to generate declarations for class members that are used repeatedly across a set of (related) classes.
C++ provides another take in this space via its template facility. Unlike the generics capability in Java, C++ templates are themselves programs that are executed by the compiler at compilation time, and resulting typically in new class declarations. (This is referred to as “template metaprogramming.”) It’s an odd sort of programming language based primarily on recursively matching type patterns, but it’s still a programming language.
None of these techniques is necessarily better than another, but they certainly provide a different set of tradeoffs. With a more comprehensive view of the various approaches, one can hopefully be more effective in leveraging the strengths of whatever language is in use.