🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

C++ Workshop - C++ Keywords, Variables, & Constants (Ch. 3)

Started by
65 comments, last by Dbproguy 16 years, 1 month ago
Quote: Original post by CondorMan
It strikes me that there is a hierarchy, starting with C++ Language at the top but what's the order beneath that? There are namespace, objects, classes, header files etc.

Namespaces, classes, structs, etc. are all elements of the C++ language, not layers upon which it is built. Header files, namespaces, and the like are all methods of grouping similar pieces of code/data todether. For example, you might have a header file containing all your function defenitions needed to render an object to the screen, which would all be wrapped in a class along with the necessary data members. This article has some good information on why/how header files are used to organize code.

Quote: Original post by CondorMan
so, for instance, is the standard namespace part of the iostream header file or the other way around? How do they relate to each other?

<iostream>, as well as all other members of the C++ standard library (see link below), are in the std namespace.

Quote: Original post by CondorMan
A further question relates to other header files (as mentioned by Oluseyi): if iostream is needed to access cin, cout etc., where can a list of all available commands or keywords be obtained, along with their respective header file? In order to use "string name;" in the source code, "#include <string>" must precede it. Sure, this will come with with experience and familiarity with the language but I suspect that there's a list somewhere.


MSDN holds all the answers

[Edited by - Driv3MeFar on June 13, 2006 8:07:23 AM]
Advertisement
Thank you. I'll check out the sites that you quoted. I'll go along with everything now and learn it verbatim, knowing that everything will crystallise in due course.

It's interesting that you said:

"<iostream>, as well as all other members of the C++ standard library (see link below), are in the std namespace."

so that reinforces the query that I had - if <iostream> is in the std namespace, why do both have to be mentioned in a listing which uses cout, cin etc.? Logic says to me that I should only have to mention std namespace as it seems "higher" than <iostream>. Having said that, I've never seen any source code which doesn't have one or more header files.

I don't want to get into detailed discussion now because that may well serve to confuse me (and, perhaps, others).
Quote: Original post by CondorMan
so that reinforces the query that I had - if <iostream> is in the std namespace, why do both have to be mentioned in a listing which uses cout, cin etc.? Logic says to me that I should only have to mention std namespace as it seems "higher" than <iostream>.


The header file iostream contains a namespace within it.

// -- within iostream header file somewhere -- //

namespace std {
// variables like cout and cin are in here
}

// ------------------------------------------- //

This means if you include iostream you still need to scope in std. It's a little confusing because all members of the iostream library are within the standard namespace, but the header file "iostream" contains the standard namespace which also contains the iostream library.

iostream header file -> namespace std -> iostream library

Hopefully that makes a little sense.

- Dave
CondorMan,

All good questions. Let me see if I can break it down a bit.

The C++ Language is a programming language, much like French or Spanish are natural languages. Both languages have semantics and to a degree syntax. The semantics of a language is what "features" it provides. By comparison, Spanish and French both have the same semantics (conjugations, sentence structure, gender, etc...), but as the vocabulary is different between the two languages they have a slightly different Syntax.

C++ shares common semantics with most modern object oriented languages including Java, C#, J#, &#106avascript, PHP, etc...And to a degree, it shares the same syntax with many of them as well - because they're all ideas spawned from the same root - The C Language. Namespaces are just one of the "features" or "semantics" of most common OO languages.

Part of the argument for an object oriented language is being able to group data with functionality and code-reuse. The ability to build a library of reusable software rather than having to write everything from scratch is the dream of every software engineer. We imagine a world where everything we could want to create is simply a matter of plugging components together without the need to write any more of the "low level" stuff. To that end, the C++ ISO Board proposed a set of standardized libraries that every ISO compliant compiler must provide. How they implement the libraries is flexible, but the components that make up the library must be consistent. This is of course the C++ Standard Library.

When working within the C++ language the compiler must know at compile-time what the declarations look like for all the functions, classes, methods, etc...you want to use. In last week's thread I posted a really good explanation of namespaces, so I wont duplicate here. It basically comes down to this, namespaces help the compiler decide which Identifier to use, in case there is more than one with the same name. In other words, think of namespaces as a Surname. There are TONS of Michaels in the world, but I want to address a specific Michael, lets say Michael WALSH. Namespaces accomplish the same goal. I could create my own cin, cout, etc...but by telling the compiler I want to use the Standard Namespace with 'std' I'm telling it WHICH cin and cout to use.

std::cin as opposed to jwalsh::cin.

As was a part of last week's quiz, there's 3 ways to identify WHICH identifier I want to use.

std::cin;            // fully qualified, us std::cin in this instance onlyusing std::cin;      // Use the STD version of cin for the rest of this scopeusing namespace std; // Look within the STD namespace for all classes for the rest of this scope


As for why we include different header files. Its pretty simple. The concepts of namespaces lies across the concept of a file. I can have a file with 12 different namespaces in it...but I can also have 12 different files all with code which is included in the same namespace. Files are a physical division of a library, while namespaces are a logical division of a library. Two different ways upon which to divide a library, and both necessary for identifying what to include in your program, and which version to use.

In the case of the Standard Library, there's about 50 different files, each which contains useful classes, etc...But I don’t want the compiler to include them ALL....that would be a performance nightmare, many of the library components are unnecessary for most tasks. So to keep my code small and program running quickly, the compiler allows me specify WHICH of the components of the library I want to use at any specific moment. To do that I simply include the header file.

Then, once I've included the header file I need to tell the compiler that I want to use the namespace contained WITHIN that file. Remember - there could be multiple namespaces within a single header...and there could be multiple versions of cin, cout, or whatever is IN the file I just included lying around my project.

I hope this helps, let us know if you have any follow-up questions.

Cheers!
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
Quote: Original post by CondorMan
So that reinforces the query that I had - if <iostream> is in the std namespace, why do both have to be mentioned in a listing which uses cout, cin etc.? Logic says to me that I should only have to mention std namespace as it seems "higher" than <iostream>. Having said that, I've never seen any source code which doesn't have one or more header files.

I don't want to get into detailed discussion now because that may well serve to confuse me (and, perhaps, others).

The above answers to your question are very good. I feel to clarify what the #include directive does. The #include directive is handled by the preprocessor before the C++ compiler proper ever sees your code. The preprocessor sees the #include, opens up the text file it points to (in this case, a file called "iostream") and pastes the entire contents of that file in the place of the #include directive.

Namespaces are part of C++ itself, and are handled by the compiler after all of the #include's and other preprocessor directives are done and over with.

Hope that helps.
Thank you for the detailed responses to my questions. I've read them a few times and it's starting to make sense.

Here's to the remainder of this week's work and to the forthcoming quiz!
CondorMan,

Are you confused by C++ namespaces or by the C++ way of using the using keyword?

I'm asking this because of this sentence in your post:
Quote: Logic says to me that I should only have to mention std namespace as it seems "higher" than <iostream>


One way to understand the using keyword lies in one of the premise of the C++ language:

Thou shall not use any undeclared symbol


As BeanDog told you, the #include preprocessor directive is used to paste the content of a file into another file. In a sense, it imports the declarations that are in the included file into the includer file. You can see the output of the preprocessor by doing this (.NET 2003, but should be very similar ofr .NET 2005):
  1. go to the project properties
  2. in the C++ properties, chose 'Command Line'
  3. in the Additional Options text bos, add
    /P / EP
    (/P = write preprocessor output, /EP = don't write #line directives in the preprocessor output)
  4. Click OK
  5. Compile your project (the project will not link, because the object files are NOT created)
  6. go to your source (probably Debug or Release)
  7. the preprocessor output have the .i extension


Don't forget to revert this project options changes if you want to be able to successfully compile and link your project. Be aware that the generated files are rather big (often several thousands of lines).

The #include directive has no real impact on the compilation - in fact, strictly speaking, it takes place before compilation, in a step called preprocessing. The goal of preprocessing is to prepare a compilation unit (the resulting .i file) to be compiled. In fact, #include is a helper because it allows you to put the declarations that might need to be used in more than one C++ file into a single file (a header file - most of the time they have a .h extension, but some of them (those of the Standard C++ Library) may have no extension). Then, instead of writing the declaration in each C++ file, you simply include the corresponding header file.

This way, you can import the declarations you need in your compilation unit.

Now that all needed symbols are known, we are able to use them. Before I continue, let speak a bit about namespaces and their usage.

Namespaces are relatively new beasts in software engineering. The current trend is to use namespaces to create packages of classes that share a same goal (for example, providing a standard library to C++ programmers). You can even add subnamespaces (to create subpackages).

The strict usage of fully qualified names may lead to source code that is difficult to read - and difficult to maintain / modify. This is expecially true when namespace names are long or when you are using symbols that are declared in subnamespaces. For example:
company::database::clientmanager::Client *client =   new company::database::clientmanager::Client(    company::database::clientmanager::ClientType::VERY_RICH);

Now that I wrote this horror, the goal of the using keyword should become clearer: while namespace are really useful because they help the definition of clearly bound units, they can lead to barely readable or even unreadable source code, which is never a good thing. the using keyword allows you to simplify the code when you need to use symbols that have been declared in a namespace.
using company::database::clientmanager;Client *client(ClientType::VERY_RICH);

This is easier to read, isn't it?

You may ask: why did he speak about #include, then namespaces, then using? That's because I feel that you misunderstood the roles of #include and using: while you beleive that they are related, in fact they are not related at all (they can't be related, because they are used in different steps of the whole compilation process). As BeanDog clearly stated, #include is a copy-paster that allow you to declare your symbols in one file and to use this declaration in many classes (hence to satisfy the first part of the C++ premise that I stated). The using keyword allows you to define a new, simpler way, to gain access to these declared symbols (hence to satify the other part of the same C++ premise).

In your example, #include <iostream> is used to import the declarations of the streams symbols, and using std; is used to simplify the access to the symbols that have been imported and that are in the "std" namespace.

I hope I have been clear enough ;)

Regards,
Hi Emmanuel

Thank you for your contribution. I hope that this part of the thread is also helpful to anyone else who's having trouble understanding the terminology.

I understand "#include" and "using".

My original concern was when constructing typical "Hello World!" source code. I realised that *both* #include <iostream> and using namespace std; (or one of the equivalent variations) was necessary but I didn't know why. I assumed that there was a "hierarchy" - for instance, I assumed that having #include <iostream> pasted the contents of iostream into a space above my source code and then, as ph33r said, iostream contains std, so why declare (possibly not the correct word, but not used in the strict programming sense of "declare") the use of std? Jeromy said that he could create several namespaces, each having cin, cout etc. and I didn't know that was possible. I understand now why it's necessary to be explicit in wanting to use std::cin, std::cout etc.

As I've said before, this will crystallise in due course. I have NO intention of letting a computer beat me!
C++ beginners often have problems to see when they should use the "declare" word or the "define" word, so you are not alone. As I already stated in the very first thread of this workshop, I don't own the book so I don't know if it contains a simple definition of these words.

Let's remember what a C++ compiler does:
  1. first, it preprocess the C++ file
  2. then it compiles the preprocessed file
  3. then it links all the compiled C++ files into one big executable file


The goal of the declaration of a C++ symbol is to tell the compiler that the symbol exists somewhere. Essentially, it says "this symbol exists somewhere, you don't have to know eaxactly where it is, and it has that name and that signature". Once a compiler knows every symbol that is used in a particular C++ file, it can compile the file and produce the object (.o or .obj) file.

The goal of the definition is tu put something behind the symbol itself.

Let's see an example:
// ----------------------- file1.h#ifndef FILE_1_H#define FILE_1_H// this is the function ** declaration **int function_plus(int a, int b);#endif // FILE_1_H

// ----------------------- main.cpp#include <iostream>// including file1 will declare the existing symbol function_plus()// so we can use it in this compilation unit#include "file1.h"int main(){  std::cout << "10 + 20 = " << function_plus(10, 20) << std::endl;}


If I stop my work here, what will happen? main.cpp will correcly compile (function_plus() is known), but what should function_plus() do? The compiler have no way to know about this problem (since you specifically told him that 'function_plus() exists somewhere') but the linker - which goal is to produce the final exe - will complain because of an undefined symbol ie an existing, declared symbol that has no real existence.

To correct the problem, let's add the function_plus() definition to correct the problem:
// ----------------------- file1.cpp#include "file1.h"int function_plus(int a, int b){  return a + b;}


The couple definition/declaration is difficult to get for a beginner (I had the exact same problems when I began C++ some years ago - the problem was even worse for me because I came from a C background and the C language don't require function declarations).

At this point, I believe that the most important thing to remember about declaration and definition is that
  • the declaration is vital for the compiler
  • the definition is vital for the linker
  • an "undeclared symbol" compilation error means that the symbol is unknown to the compiler (check why)
  • an "undefined identifier" linker error means that the symbols is known by the compiler, is corectly used, but don't really exists.
  • a "multiple definition" linker error means that a symbol has been defined more than once in the whole project.


I guess I'm going to try to find a copy of this book on ebay. I feel that I'm not helping very much if I don't know what is the exact subject.

Regards,
Quote: Original post by Emmanuel Deloget
Let's remember what a C++ compiler does:
  1. first, it preprocess the C++ file

  2. then it compiles the preprocessed file

  3. then it links all the compiled C++ files into one big executable file

The preprocessor "preprocesses" the file. The compiler compiles the preprocessed file. The linker links the generated object files.

What you have referred to is the toolchain, not just the compiler. The MSVC++ command line compiler, cl.exe, will invoke the linker, creatively named link.exe, by default unless you suppress that behavior with a flag. The preprocessor for MSVC++ has been integrated into the compiler binary.

GCC, on the other hand, still maintains a distinct C preprocessor binary, cc, as well as a C++ compiler, g++ and linker, ld. g++ will call cc and ld automatically. (We ignore other compilers included in GCC as this is a C++ workshop.)

Pedantic, I know, but since we're discussing terminology, we might as well get it right. Also, Emmanuel, you should close your <li> tags in order to be valid XHTML. For future reference. [smile]

This topic is closed to new replies.

Advertisement