1

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

asked Apr 22, 2016 at 18:23
7
  • 10
    Please stop using using namespace std; in header files. Further reading: Why is "using namespace std" in C++ considered bad practice? Commented Apr 22, 2016 at 18:26
  • A recent question. Commented Apr 22, 2016 at 18:29
  • Why does ADate's constructor take regular ints, but isValidDate take unsigned ints? You're kinda begging for signed/unsigned issues. Commented Apr 22, 2016 at 18:30
  • 3
    The prototype for function isValidDate is inside the namespace A in the header file, so it's really not global. Commented Apr 22, 2016 at 18:47
  • 2
    Time for a code review (once you fix this bug). Checkout codereview.stackexchange.com Commented Apr 22, 2016 at 20:12

1 Answer 1

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().

answered Apr 22, 2016 at 20:25

2 Comments

Ok, thank you for the explanation. Just for completeness: the member methods don't need the specifier, because of the class specifier of the class which was declared within the namspace. Is that correct?
@PaceyW. Correct the class name must be exactly resolved to a specific class (if multiple classes match this is a compile time error). Since there is now an exact match to the class you can match the definition to the declaration.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.