tags:

views:

123

answers:

4

Although you wouldn't want to do this, if you have a namespace COMPANY, and a class in that namespace SOMECLASS. Why is it that in the .cpp file, you might define the functions as

COMPANY::SOMECLASS::someFunction()
{}

But in main, I get errors for doing:

int main() {
  COMPANY::SOMECLASS::someFunction();
}

but instead you declare the namespace and do something like:

using COMPANY::SOMECLASS;

int main() {
  someFunction();
}

My compile errors are:

1>c:\documents and settings\wongj\desktop\main.cpp(14) : error C2065: 'saver1' : undeclared identifier
1>c:\documents and settings\wongj\desktop\main.cpp(14) : error C2277: 'JWong::SavingsAccount::{ctor}' : cannot take address of this member function
1>c:\documents and settings\wongj\desktop\main.cpp(14) : error C2061: syntax error : identifier '{ctor}'

SavingsAccount.cpp:

#include "SavingsAccount.h"

// initialize static data member
double JWong::SavingsAccount::annualInterestRate = 0;

// default constructor, set savingsBalance to 0
JWong::SavingsAccount::SavingsAccount() : savingsBalance(0)
{}

// constructor
JWong::SavingsAccount::SavingsAccount(double savingsBalance) : savingsBalance(savingsBalance)
{}

double JWong::SavingsAccount::getSavingsBalance()
{
    return savingsBalance;
}

void JWong::SavingsAccount::setSavingsBalance(double savingsBalance)
{
    this->savingsBalance = savingsBalance;
}

// added these functions to make program cleaner
double JWong::SavingsAccount::getMonthlyInterest()
{
    return monthlyInterest;
}

void JWong::SavingsAccount::setMonthlyInterest(double monthlyInterest)
{
    this->monthlyInterest = monthlyInterest;
}

// returns monthly interest and sets savingsBalance to new amount
double JWong::SavingsAccount::calculateMonthlyInterest()
{
    double monthlyInterest = savingsBalance * SavingsAccount::annualInterestRate / 12; 
    setSavingsBalance(savingsBalance + monthlyInterest);
    setMonthlyInterest(monthlyInterest);
    return monthlyInterest; 
}

void JWong::SavingsAccount::modifyInterestRate(double newInterestRate)
{
    SavingsAccount::annualInterestRate = newInterestRate;
}

double JWong::SavingsAccount::getAnnualInterestRest()
{
    return SavingsAccount::annualInterestRate;
}   

SavingsAccount.h

#ifndef JWONG_SAVINGSACCOUNT_H
#define JWONG_SAVINGSACCOUNT_H

namespace JWong
{
    class SavingsAccount
    {
    public: 
        // default constructor
        SavingsAccount();
        // constructor
        SavingsAccount(double savingsBalance);

        double getSavingsBalance();
        void setSavingsBalance(double savingsBalance);
        double calculateMonthlyInterest();
        double getMonthlyInterest();
        void setMonthlyInterest(double monthlyInterest);

        // static functions
        static void modifyInterestRate(double newInterestRate);
        static double getAnnualInterestRest();
    private:
        double savingsBalance;

        // static members
        static double annualInterestRate; 
        double monthlyInterest;
    };
}



#endif

main.cpp:

#include <iostream>
#include <iomanip>

#include "SavingsAccount.h"
using std::cout;
using std::setprecision;
using std::fixed;
//using JWong::SavingsAccount;

int main()
{
    JWong::SavingsAccount::SavingsAccount *saver1 = new JWong::SavingsAccount::SavingsAccount(2000.00);
}
A: 

The using directive may be used in C++ source files, just not in header files, so you could use a using directive for the ".cpp" file that you mentioned. If it is not being used, it is possible that whoever created the file simply decided not to do it, or perhaps it was necessary in order to avoid a name clash (which is the whole reason why namespaces exist). The one place to never put a using directive is in a header file, because doing so completely undermines the point of having namespaces in the first place (though, unfortunately, if you do that the compiler won't say anything as it is technically permissible to do).

P.S.: By "using directive" I am referring to a directive that is in the global scope and that exposes the contents of a namespace. It is acceptable to have a using directive in a header file if it is bringing symbols from some other namespace (assuming that is to be part of the API) and also for preventing functions from baseclasses from being overshadowed (i.e. if you defined Derived::foo, you might want using Base::foo).

Michael Aaron Safyan
Using directives are certainly allowed in header files... of course, that doesn't mean it's a good idea to put them there, and most would consider it a bad idea http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5
Nick Meyer
@Nick, yes, I am aware that they are permitted/legal; I did not mean to imply that they were not, simply that one should not place them there, as it completely defeats the purpose of having namespaces in the first place. IMHO, it would be nice if compilers complained very loudly when seeing a "using" directive in the global scope within a file with a name ending in ".h". But, alas, they don't.
Michael Aaron Safyan
I agree, I have been burned by the same thing many times. Best thing to do is make it punishable by death and do code reviews ;)
Nick Meyer
A: 
int main() {
  COMPANY::SOMECLASS::someFunction();
}

is certainly legitimate, as is

using COMPANY::SOMECLASS;

int main() {
  someFunction();
}

The latter just saves you typing. One reason to use the first, though, is to avoid clashes between multiple namespaces. For example, if someday you decide this code needs to use a library with a class foo that declares a static someFunction():

using COMPANY::SOMECLASS;
using foo;

int main() {
  someFunction(); // Uhh, which someFunction()?
}

See [27.5] Should I use using namespace std in my code? from the C++ FAQ.

Nick Meyer
`using COMPANY::SOMECLASS;int main() { someFunction();}`is not OK because `SOMECLASS` is presumably a class, not a namespace.
Potatoswatter
A: 
namespace COMPANY {
   class SOMECLASS {
       static void someFunction();
       // Here you can call it COMPANY::SOMECLASS::someFunction,
       // SOMECLASS::someFunction, or simply someFunction.

       // You may define it as someFunction.
   };
   // Here you can call it COMPANY::SOMECLASS::someFunction,
   // or SOMECLASS::someFunction.

   // You may define it as COMPANY::SOMECLASS::someFunction or
   // SOMECLASS::someFunction.
}

// Here you must call it COMPANY::SOMECLASS::someFunction,

// You may define it as COMPANY::SOMECLASS::someFunction:

COMPANY::SOMECLASS::someFunction()
{}

// Or call it the same way:

int main() {
  COMPANY::SOMECLASS::someFunction();
}

// If you import the namespace,
using namespace COMPANY;

// or just the class,
using COMPANY::SOMECLASS;

// now you may call it SOMECLASS::someFunction

int main() {
  someFunction(); // ERROR - but you cannot call it simply someFunction
} // outside of the class it lives in.
Potatoswatter
+1  A: 

The problem is simply in your declaration in main - you're accessing constructor, not the type, and you can't really reference the constructor directly.

Change main to:

int main()
{
    JWong::SavingsAccount *saver1 = new JWong::SavingsAccount(2000.00);
}

...and you should be good to go.

Nathan Ernst
So is JWong::SavingsAccount the namespace::class or namespace::constructor? And why is it different for other functions (e.g. JWong::SavingsAccount::ModifyInterestRate. It seems like the functions I use the full declaration but the constructorI do not?)
Crystal
What you're actually doing is declaring an instance of a type here, a pointer to a `JWong::SavingsAccount` and initializing it with a heap-allocated instance. So, you're referring to namespace::typename in both instances. in `new JWong::SavingsAccount(2000.00)`, the actual function invocation is to operator new, and you're passing the arguments to this operator that will in turn be passed to your constructor.
Nathan Ernst