C and C++ notes / Structuring

From Helpful
Jump to navigation Jump to search

Notes related to C and C++

Note: Some notes describe behaviour common to most variants - for C mostly meaning C89 (and a bit of C99), unless mentioned otherwise.

This article/section is a stub — some half-sorted notes, not necessarily checked, not necessarily correct. Feel free to ignore, or tell me about it.


Why the header / code split?

Namespaces (C++)

  • namespaces allow you to avoid name clashes (if used moderately well)
  • namespaces allow you to organize, regardless of contained file (for example, cout is not a member of std until you include iostream)
//You may regularly do something like
namespace example {
  int i;
  char connect(char *);

//anonymous namespaces are also useful to avoid some namespace pollution. For example, you can write app code like:
namespace {
  char connect(char *);


Say you placed that into nsexample.h and are now writing an app that wants to use it. You can...

  • explicitly get members, using the scope operator, ::
#include <iostream>
#include "nsexample.h"
void main(void) {
  std::cout << example::i << std::endl;

  • Alias a namespace - same idea, saves some typing,
#include <iostream>
#include "example.h"
namespace e = example;
void main(void) {
  std::cout << e::i << std::endl;

  • import all of a namespace's references into the current scope:
#include <iostream>
#include "example.h"
using namespace std;
using namespace example;
void main(void) {
  cout << i << endl;

  • import specific names -- and you can choose to do so into specific scopes:
#include <iostream>
#include "example.h"
using std::cout;
using std::endl;
void main(void) {
  using example::i;
  cout << i << endl;

Roughly speaking, the first style is unambiguous, but can be very verbose. The second can help brevity when you can, say, shorten very_long_name:: into vln::

The third is considered bad style. Names may clash. In this case it's very likely, with i.

The fourth style can be a reasonable balance between brevity and clarity.

You should, in general, think twice when you're importing into the global namespace, and think twice when importing an entire namespace. (For example, typing std:: in all references into that namespace versus using using namespace std; at the top of a file)

The basic reason is that names can clash, because you're polluting one namespace with the contents of another. The differences and preferences relates to how.

This example has i, std has count (in <algorithm>), and there are many other names that both you and other people will have used. If you're aware of this potential problem you won't get into much trouble, or avoid the possible trouble in the first place.

There are some objective and some subjective arguments to what you should do in which situation. It generally comes down to taste plus a few agreed-on don'ts.

  • trivial example code can easily use using. There's not enough code for clashes.
  • using makes code shorter and thereby more readable
  • ...but for some names may make it more ambiguous and thereby less readable
    • things that may exist in multiple namespaces may include things like count, sin, cos, and such.
    • ...while people who redeclares things like cout should probably be foam-batted.
  • It is generally considered poor style to import namespaces into the global namespace - because it's asking for name clash trouble. And nullifies most of the point and organizations of namespaces.
  • In general, never use a using in a header file. It propagates everywhere so contaminates other people's namespaces, which is poor style and asking for trouble.
  • don't make libraries that pollute namespaces (except their own)
  • polluting your own app's namespace is your own issue.

  • You can place using into more local scopes -- your own namespace, even specific functions.
  • std:: is short enough to type
  • you can alias namespaces:
is a clearer reference
  • ...but using names present in std:: is generally poor style, so there is rarely ambiguity

using std can be a bad idea because there are some names that might clash with yours. Only a few, but it'll hapen at some point (e.g. count)