Here are a demo code from C++ primer plus about using using-directive and using-declaration across header files and cpp files, I've made some modification to remove the using declarations in other function to have cout and end and the code errored:
- namesp.h
#include <string>
#include <iostream>
namespace pers
{
struct Person
{
std::string fname;
std::string lname;
};
void getPerson(Person &);
void showPerson(const Person &);
};
namespace debts
{
using namespace pers;
struct Debt
{
Person name;
double amount;
};
void getDebt(Debt &);
void showDebt(const Debt &);
double sumDebts(const Debt[], int);
}
- namesp.cpp
#include "namesp.h"
namespace pers
{
using std::cin;
using std::cout;
using std::endl;
void getPerson(Person &p)
{
cout << "Enter first name: ";
cin >> p.fname;
cout << "Enter last name: ";
cin >> p.lname;
}
void showPerson(const Person &p)
{
cout << p.lname << ", " << p.fname;
}
};
namespace debts
{
void getDebt(Debt &b)
{
getPerson(b.name);
cout << "Enter debt: ";
cin >> b.amount;
}
void showDebt(const Debt &b)
{
showPerson(b.name);
cout << ": $" << b.amount << endl;
}
double sumDebts(const Debt bs[], int n)
{
double sum;
for (int i = 0; i < n; ++i)
{
sum += bs[i].amount;
}
return sum;
}
}
- namessp.cpp
#include <iostream>
#include "namesp.h"
void other(void);
int main(void)
{
other();
return 0;
}
void other(void)
{
using namespace debts;
// using namespace pers;
// using std::cout;
// using std::endl;
Person dg = {"Doodles", "Glister"};
showPerson(dg);
cout << endl; // ERROR: cout and endl was complained no declaration in the scope
Debt zippy[3] = {{{"Alice", "Jane"}, 100.10}, {{"Bob", "Marley"}, 90.10}, {{"Sam", "Peters"}, 80.10}};
int i;
for (i = 0; i < 3; ++i)
{
showDebt(zippy[i]);
}
cout << "Total debt: $" << sumDebts(zippy, 3) << endl;
return;
}
- error:
$ g++ namesp.cpp namessp.cpp 1 ↵
namessp.cpp: In function ‘void other()’:
namessp.cpp:20:5: error: ‘cout’ was not declared in this scope
cout << endl;
^~~~
namessp.cpp:20:5: note: suggested alternative:
In file included from namessp.cpp:1:0:
/usr/include/c++/7/iostream:61:18: note: ‘std::cout’
extern ostream cout; /// Linked to standard output
^~~~
namessp.cpp:20:13: error: ‘endl’ was not declared in this scope
cout << endl;
^~~~
namessp.cpp:20:13: note: suggested alternative:
In file included from /usr/include/c++/7/iostream:39:0,
from namessp.cpp:1:
/usr/include/c++/7/ostream:590:5: note: ‘std::endl’
endl(basic_ostream<_CharT, _Traits>& __os)
^~~~
Based on my understading, function another uses a using directive using namespace debts, since using directive is transitive, it implicitly calls using namespace pers. But why cout and endl(viable through using declarations in namespace pers) are not visible in function another?
namessp.cppit will not know anything that happened in thenamesp.cppsource file. That include theusingstatements in thepersnamespace.namesp.cppandnamessp.cppwhen seeing only the names.translation unit, if I'm understanding this right, the problem occurs in the preprocessing stage ofnamessp.cpp(onetranslation unit), which basically replaces thenamesp.hwith its content. But innamesp.h, namespacepersdoesn't have those using declarations that nominatecoutandendl(those using declarations are in thepersnamespace extension innamesp.cpp(anothertranslation unit)), so those variables are not visible in functionotheras a result.