Namespaces, Includes, and the Standard Library

A quick introduction to namespaces in C++, alongside the standard library and how we can access it
This lesson is part of the course:

Making Games with SDL

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

14.jpg
Ryan McCombe
Ryan McCombe
Posted

This lesson is a quick introductory tour of functions within C++. It is not intended for those who are entirely new to programming. Rather, the people who may find it useful include:

  • those who have completed our introductory course, but want a quick review
  • those who are already familiar with programming in another language, but new to C++
  • those who have used C++ in the past, but would benefit from a refresher

It summarises several lessons from our introductory course. Anyone looking for more thorough explanations or additional context should consider Chapters 7 and 8 of that course.

Previous Course

Intro to Programming with C++

Starting from the fundamentals, become a C++ software engineer, step by step.

Screenshot from Cyberpunk 2077
Screenshot from The Witcher 3: Wild Hunt

The #include Directive

The most typical way we import code defined in another file is through an #include directive:

// Same Directory
#include "math.cpp"

// Child Directory
#include "some-subfolder/math.cpp"

// Parent Directory
#include "../math.cpp"

A directive is something we include in our code that will be detected and acted upon by the C++ preprocessor.

The preprocessor is a tool that sits between our code and the compiler. Based on any directives we have, the preprocessor modifies our source code before it is received by the compiler. We cover the preprocessor in more detail later.

The include directive performs a crude copy-and-paste operation on our code before it is compiled. Because of this, we can just use included code as if it were in the same file we’re working on:

// math.cpp
int add(int x, int y) {
  return x + y;
}
// main.cpp
#include "math.cpp"

int main() {
  Add(x+y);
}

In a project with a more complicated web of include directives, this recursive copy-and-paste process is liable to attempt to include the same file twice:

// geometry.cpp
float Pi{3.14f};
// math.cpp
#include "geometry.cpp"
// main.cpp
#include "math.cpp"
#include "geometry.cpp"

After resolving all the #include directives, main.cpp is including geometry.cpp and then indirectly including it again through math.cpp

This will result in a compilation error because we’re now defining a variable called Pi twice. To solve this, for any file that is intended to be included in other files, we should add the #pragma once directive to ensure it never gets included more than once:

// geometry.cpp
#pragma once

float Pi{3.14f};
// math.cpp
#pragma once

#include "geometry.cpp"

Namespaces

Namespaces are the primary way to organize code in large applications

namespace Math {
  int Add(int x, int y) {
    return x + y;
  }

  // Namespaces can be nested
  namespace Geometry {
    float Pi{3.14f};
  }
}

Scope Resolution Operator ::

Access to namespaces, and different scopes in general, can be done using the scope resolution operator ::

int Result{ Math::Add(1, 2)};
float HalfPi{Math::Geometry::Pi / 2};

The Standard Library

C++ comes with a large standard library, which contains a large number of generally useful code. Standard library functionality is typically included using < and > as part of an #include directive.

One of the most common standard library features we will want is the ability to create strings:

// The standard library's string implementation
#include <string>

Strings, and most standard library types and functionality are available within the std namespace:

#include <string>

int main() {
  std::string Greeting{"Hello"};
}

std::cout

By including <iostream> we get access to some useful input and output functionality.

// Ways to interact with input and output
#include <iostream>

The std::cout object allows us to stream content to our terminal using the << operator, thereby letting us see program output:

#include <string>
#include <iostream>

int main() {
  std::string Greeting{"Hello"};
  std::cout << Greeting;
}

This program yields the following output:

Hello

The << operator returns the reference to std::cout, so we can keep streaming content to it as a larger expression:

#include <string>
#include <iostream>

int main() {
  std::string Greeting{"Hello"};

  // The << operator can be chained
  std::cout << Greeting << " World";
}
Hello World

We can insert line breaks into our output using the \n sequence, or by streaming a std::endl object:

#include <iostream>

int main() {
  std::cout << "After this, there is a break\n";
  std::cout << "after this too!" << std::endl;
  std::cout << "This will\nspan two lines";
}
After this, there is a break
after this too!
This will
span two lines

using Statements

When we’re repeatedly going to be using a variable or function from a namespace, it can be helpful to add a using statement. This can be within the global scope, where it will apply to an entire file, or just within the scope of a specific block:

void MyFunction() {
  using std::cout, std::endl;

  // In the rest of this function, we can now
  // use cout and endl without needing to
  // specify the std:: prefix
  cout << "This works!" << endl;
}

If we want to refer to a whole namespace without qualification, we can have a using namespace statement:

void MyFunction() {
  using namespace std;

  // Now, anything in the std namespace can be
  // used, without needing prefixed with std::
  cout << "This works!" << endl;
}

The using namespace statement should generally be restricted, as it bypasses the purpose of having a namespace in the first place. When files get more complex, it can be difficult to determine where functions and variables are coming from if omit namespace qualifiers.

If we do want to have using namespace statements, we should prefer using them just within the specific function we need them, rather than across an entire file.

Was this lesson useful?

Edit History

  • — First Published

Ryan McCombe
Ryan McCombe
Posted
This lesson is part of the course:

Making Games with SDL

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Whirlwind Tour of C++ Basics
  • 25.Making Minesweeper with C++ and SDL2
  • 26.Project Setup
  • 27.GPUs and Rasterization
  • 28.SDL Renderers
DreamShaper_v7_cyberpunk_woman_playing_video_games_modest_clot_0.jpg
This lesson is part of the course:

Making Games with SDL

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access!

This course includes:

  • 24 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Next Lesson

Conditionals and Loops

A quick introduction to conditionals and loops in C++, and how we can use them to control how our program executes
a52.jpg
Contact|Privacy Policy|Terms of Use
Copyright © 2023 - All Rights Reserved