15

I'm taking a class on Object Oriented Programming in C++. In a recent assignment I defined a member function within a struct. My instructor explained that, although it's compilable to use member functions within structs, he would prefer we didn't, for backward compatibility with C, and (especially in this beginner class) to practice good data encapsulation- we should use a struct for types that contain mostly data, and a class for applications that benefit from more procedural encapsulation. He indicated that this practice comes from the history of structs/classes in C++, which is what I'd like to know more about.

I know that structs are functionally the same as classes except for default member/inheritance access. My question is:

Why are structs AND classes included in C++? From my background in C#, where structs and classes have important differences, it seems like struct in C++ is just syntactic sugar for defining classes with default public-ness. Is it?

I'm not looking for opinions on when/why one should be used instead of the other- I was born well after these constructs were, and I'm looking for the history of them. Were they conceived together? If so, why? If not, which came first, and why was the second added? I realize that there are many venerable elders within this community who may have living memory of these features' origins, and links to standards publications, or examples of code, where both, one, or the other first appeared, will add to answers' helpfulness.

Please note, this question is not:

Community
  • 1
  • 1
Michael Hoffmann
  • 2,411
  • 2
  • 24
  • 42

4 Answers4

8

To ease development of polyglot headers.

C and C++ are separate languages, but the C++ language is designed to provide a large useful common subset with the C language. Several commonly used constructions in the C++ language have the same meaning (or nearly so) as they have in the C language. In the case of struct, the C++ language defines it as syntactic sugar for class that approximates the behavior of a struct in the C language, namely that members are public by default. Thus a program or part thereof can be written in this common subset. This allows, for example, a library to provide a single header file that declares the same API to both programs written in the C language and programs written in the C++ language.

Some differences between the C language and the C++ language are listed in a question that has since been closed as too broad. From the perspective of somebody programming in this common subset language, these differences can be treated as "implementation-defined behavior", where compilers for the C language produce one behavior and compilers for the C++ language produce the other.

In fact, the C++ standard provides mechanisms to aid development of polyglot programs that are valid in both C and C++ languages. The extern "C" linkage specifier allows a program to be written partly in C and partly in C++. And the __cplusplus symbol is used in #ifdef __cplusplus conditions to conditionally enable macros, linkage specifiers, and other specifics that only one of the two languages is supposed to see.

Community
  • 1
  • 1
Damian Yerrick
  • 4,602
  • 2
  • 26
  • 64
  • 3
    Differences are often subtle. It is dangerous to tell a beginner there is a common subset without clarifying which that is (OTOH this would be too broad). It is generally better to treat them as different languages. – too honest for this site Oct 06 '15 at 18:05
  • No, the edit is factually wrong. It is not just IDB. – too honest for this site Oct 06 '15 at 18:13
  • @Olaf The behavior is defined by the C standard in one way and by the C++ standard in another way. A C compiler can be used as an implementation of the common subset, with the differing behaviors conforming to C. So can a C++ compiler, with the differing behaviors conforming to C++. Each compiler defines these behaviors by specifying which language it compiles. So it's not IDB from the perspective of C or C++, but it is IDB from the perspective of the common subset. – Damian Yerrick Oct 06 '15 at 18:16
  • 1
    With the same argument you could say Modula-2 or Java code shares a common subset with C and C++ with all differences being just IDB. Nonsense, you have the last word. – too honest for this site Oct 06 '15 at 18:20
  • 3
    @Olaf That's why I emphasized __large useful__. The common subset between C and Java isn't large enough to be very useful, not nearly so much as the common subset between C and C++ that practically encourages [polyglot programming](https://en.wikipedia.org/wiki/Polyglot_%28computing%29) where possible. – Damian Yerrick Oct 06 '15 at 18:22
  • @tepples, can you provide some citation of this? Yes, they're syntactically similar, and one stemmed from the other, but is polyglot programming between C++ and C encouraged in any standards? Is that a contributor to why `class` was added, or a defining guideline for standards published since then? Or is this just common practice because of the common subset the languages happen to share? From a millennial/C# perspective, I agree with @Olaf and tepples- It seems that most of the [C-family languages](https://en.wikipedia.org/wiki/List_of_C-family_programming_languages) share a "common subset". – Michael Hoffmann Oct 06 '15 at 18:37
  • 1
    @tepples: Any non-trivial program will have to use features specific to the language. If you program C-style in C++, you soon will have to rectify why you do not use the features of that language, or why you do not use C with **its** specific features. For a starter: tentative definitions, prototype-style declarators, VLAs, enums, (not) casting `void *`, `malloc` vs. `new`, `const` objects, headers, etc. If you have a car with four wheels: do you only use three of them, putting a weight at the right position? – too honest for this site Oct 06 '15 at 18:48
  • @MichaelHoffmann maybe not "encouraging" but the fact that the C++ standard library must provide C standard library header files is a pretty clear indication that C++ code should be able to mix in C code, even if only for compatibility's sake. There are also many things the C++ library doesn't provide that ultimately end up being implemented in C (often wrapped in C++ but still). Networking is a major example of this, there's no standard C++ networking facility. I guess it depends if you include the library in this discussion. – anthonyvd Oct 06 '15 at 19:15
  • 1
    @MichaelHoffmann "is polyglot programming between C++ and C encouraged in any standards?" The existence of `#ifdef __cplusplus` and the `extern "C"` linkage specifier for use in polyglot headers are evidence of yes. I will update. – Damian Yerrick Oct 06 '15 at 20:47
  • There is also a `__STDC__` macro in C. Does this encourage writing non-standard code then? And you can also link Fortran or Assembler code. The C standard even mentions an [`asm`](http://port70.net/~nsz/c/c11/n1570.html#J.5.10) construct. Do these actually encourage mixing-in these languages? They are there to cover some niches of programming the standard does not cover. Kinda providing a track off the road into roadless area. (And some people think their SUVs are fit for this, wondering their axes break after few km) – too honest for this site Oct 07 '15 at 11:41
  • @Olaf So `extern "C"` is not quite as strong of evidence as `__cplusplus`, as other languages support C linkage. But C has a standard, and C++ has a standard, and the two languages defined by these standards have a useful common subset for which C++ provides explicit tools to make polyglot programs. The same cannot be said of Fortran. As for `asm`, it'd be different if the contents of `asm` were covered by some standard. – Damian Yerrick Oct 07 '15 at 12:20
4

In the old days (late 1980s or early 1990s), a C++ compiler (then called cfront) translated C++ code to C code. That C++ was widely different from current C++11 or C++14 (or even old C++03).

I don't remember the details, but it could have happened that struct at that time was parsed completely, but passed unchanged into the generated C code, while class was preprocessed to something different (and was translated to a struct).

I might be completely wrong, this is from my human memory, and I only used (on SunOS3, Sun3/160 workstations) a couple of times that cfront. It left me unimpressed, but interested. At that time, the translation to C code added a significant time to the build process. But things have changed a lot, translating to C makes a lot of sense today...

(In those days, a hello world program in Ada took 5 minutes to compile, and with cfront it might be 3 minutes, but in C it was less than a minute)

Later on, the definition of C++ changed, and struct foo { was indeed equivalent to class foo{ public:, but I am not sure that was the case in the primordial C++ compiler.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
2

Both were included in the original C++ language, but struct long predates C++ in the C language.

C++ includes structs because it inherited them from C. There was no reason to remove them from C++ and break existing C code bases that may be compiled with a C++ compiler.

C++ introduces class as a new keyword. Presumably the keyword was introduced to provide the option of differentiating newly created C++ classes from existing structs in legacy C code bases.

Mark B
  • 95,107
  • 10
  • 109
  • 188
1

C++ is mostly a superset of C. So (mostly) if you can do something in C you can do it in C++. Structs are a C feature and were included in C++. Refer to this for the reasons C++ isn't a true superset: Where is C not a subset of C++?

Community
  • 1
  • 1
Michael Albers
  • 3,721
  • 3
  • 21
  • 32
  • "mostly ..." Not really. Differences are quite subtle sometimes. One should not invoke this impression to a beginner, this leads to more problemss than good. – too honest for this site Oct 06 '15 at 18:08
  • @Olaf Which is why I added the link to show the differences. – Michael Albers Oct 06 '15 at 18:09
  • Ok, I removed the DV. But you did not answer the question actually. Please elaborate. – too honest for this site Oct 06 '15 at 18:10
  • Somehow, this post has made me realise that C++ is the original "Turn it up to 11" by being "one more" than C – user3791372 Oct 06 '15 at 18:13
  • @user3791372 Always a good day when someone quotes the great Nigel Tufnel. :) – Michael Albers Oct 06 '15 at 18:15
  • This doesn't mention anything about classes, nor why they're both included if they do pretty much the same thing. No DV because the link is helpful, but not really a complete answer to my question. – Michael Hoffmann Oct 06 '15 at 19:11
  • @Olaf The "mostly" implies that there's a way to measure the amount of difference and having some threshold where it will be considered "mostly". For example the pre C99 differences mentioned in the link is a questionable construct, an obsolete construct and two construct that's probably not often used - I would consider those differences quite small, then of course there's more important differences. I think the most common difference is that `malloc` cannot be used the way it's used in `C` and that `new` and `class` is perfectly valid identifiers in `C`. – skyking Oct 07 '15 at 07:44
  • Bjarne himself said that C++ is a superset of C. – Dan P. Nov 25 '22 at 04:40