following class ADate is declared enclosed by namespace A
.h file
#ifndef ADATE_H
#define ADATE_H
namespace A{
class ADate
{
public:
static unsigned int daysInMonth[];
private:
int day;
int month;
int year;
public:
ADate(const unsigned int day, const unsigned int month, const unsigned int year);
};
bool isValidDate(const unsigned int day, const unsigned int month, const unsigned int year);
}
#endif // ADATE_H
.cpp file:
#include "adate.h"
using namespace A;
unsigned int ADate::daysInMonth[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
ADate::ADate(const unsigned int day, const unsigned int month, const unsigned int year) :
day{day},
month{month},
year{year}
{
if(!isValidDate(day,month,year)){
throw string{"invalid Date"};
}
}
bool isValidDate(const unsigned int day, const unsigned int month, const unsigned int year)
{
if(month < 1 || month > 12){
return false;
}
if(day < 1 || day > ADate::daysInMonth[month-1]){
return false;
}
if(year < 1979 || year > 2038){
return false;
}
return true;
}
One should think that the code above can be compiled successfully. However, this is not that way, cause an undefined reference to `A::isValidDate(unsigned int, unsigned int, unsigned int)' occurs.
I don't understand why I have to use the namespace-specifier as prefix for the global function 'isValidDate'.
Can you explain why. Thank you
1 Answer 1
Because of the namespace lookup rules.
See: http://en.cppreference.com/w/cpp/language/lookup
For variables, namespaces, classes, etc (apart from functions), name lookup must produce a single declaration in order for the program to compile.
For functions name lookup can associate multiple declarations (which are then resolved by argument comparison).
So:
bool isValidDate(const unsigned int day, const unsigned int month, const unsigned int year)
{
// CODE
}
Is both a declaration and a definition. The namespace resolution did not need to resolve the name of the function to the A::isValidDate()
function so it does not. Instead it adds another declaration into the current scope for isValidDate()
.
using namespace std;
in header files. Further reading: Why is "using namespace std" in C++ considered bad practice?ADate
's constructor take regularint
s, butisValidDate
takeunsigned int
s? You're kinda begging for signed/unsigned issues.isValidDate
is inside the namespaceA
in the header file, so it's really not global.