Namespaces group declarations and prevent collisions across libraries and application modules. A qualified name makes ownership explicit, while a using declaration imports one selected name into the current scope. A using directive imports an entire namespace and is especially hazardous in headers.
A using declaration imports one selected name; a using directive makes all names from a namespace candidates for lookup. The broader directive is risky in headers because it changes every including file.
#include <iostream>
namespace metric { double distance(double km) { return km * 1000; } }
namespace imperial { double distance(double miles) { return miles * 1609.344; } }
int main() {
std::cout << metric::distance(2) << '\n';
std::cout << imperial::distance(2) << '\n';
}
2000
3218.69
An unnamed namespace gives names internal linkage within one translation unit and is useful for source-file implementation details. Do not place public types in unnamed namespaces in headers.
Never write using namespace std in a public header because every includer inherits the ambiguity. Prefer std:: qualification or narrow using declarations inside a function. Use an unnamed namespace in a source file for internal-linkage helpers that should not be visible outside that translation unit.
Namespace aliases can shorten deeply nested library names locally. Inline namespaces support versioned library APIs, but application code rarely needs them. Keep namespace and directory boundaries aligned enough that a reader can locate the owner without depending on an IDE search.
Namespaces prevent unrelated libraries from claiming the same global identifier. Prefer qualified names at integration boundaries and narrow using declarations inside small scopes. A header-level using namespace directive leaks lookup changes into every translation unit that includes it.
Namespace aliases are useful for long library names while preserving ownership. Keep declarations and out-of-line definitions in the same namespace; otherwise the linker may report an undefined reference even though a similarly named function exists.
#include <iostream>
#include <string>
namespace audit { std::string format() { return "audit"; } }
namespace ui { std::string format() { return "ui"; } }
int main() {
std::cout << audit::format() << ' ' << ui::format() << '\n';
}
audit ui
Qualification makes ownership explicit and avoids an ambiguous unqualified call.
Try this next
0 of 2 completed
It imports names into every source file that includes the header and can create collisions far from the declaration.
It starts lookup in the global namespace rather than the current nested scope.
It gives declarations internal linkage so they remain private to the current source file.
Explore 500+ free tutorials across 20+ languages and frameworks.