friendship and namespace issue - c++

I'm having troubles with friendship between a class of a namespace and a function as below:
How to tell that the friend function is outside of the namespace?
Thanks
namespace NS
{
class Class
{
public:
Class();
virtual ~Class();
private:
void Foo();
friend void Bar(Class&);
};
}
void Bar(NS::Class& c)
{
c.Foo();
}

By using the scope operator ::
friend void ::Bar(Class&);
This tells the compiler that Bar is in the global scope.
Apparently the Bar function needs to be declared before it's used in the friend declaration when using the scope operator. The problem is that for Bar to be declared you need to declare both the namespace NS and the class NS::Class.
Something like this
namespace NS
{
class Class;
}
extern "C"
{
void Bar(NS::Class& c);
}
namespace NS
{
class Class
{
public:
Class();
virtual ~Class();
private:
void Foo() {}
friend void ::Bar(Class&);
};
}
void Bar(NS::Class& c)
{
c.Foo();
}

Related

Does friend functions must be defined in header files? [duplicate]

Im trying to define a class friend function outside the namespace like this:
namespace A{
class window{
private:
int a;
friend void f(window);
};
}
void f(A::window rhs){
cout << rhs.a << endl;
}
Im getting an error said that there is ambiguity. and there is two candidates void A::f(A::window); and void f(A::window). So my question is :
1) How to make the global function void f(A::window rhs) a friend of the class A::window.
EDIT: (After reading the answers)
2) why do I need to qualify the member function f inside window class to be global by doing ::f(window) ?
3) why do I need to predeclare the function f(A::window) in this particular case, whereas when the class is not a defined inside a namespace it's okey for the function to be declared after the function is declared a friend.
As well as adding a :: you need to forward declare it, e.g.:
namespace A { class window; }
void f(A::window);
namespace A{
class window{
private:
int a;
friend void ::f(window);
};
}
void f(A::window rhs){
std::cout << rhs.a << std::endl;
}
Note that for this forward declaration to work you need to forward declare the class too!
This should do it: you need forward declares to make it clear f is in the global namespace (and not file static):
#include <string>
#include <iostream>
using namespace std;
////// forward declare magic:
namespace A{ class window; }
void f(A::window rhs);
//////
namespace A {
class window {
private:
int a;
friend void ::f(window);
};
}
void f(A::window rhs) {
cout << rhs.a << endl;
}
int main()
{
}
Using ::, you can also friend a class from the outer wrapping namespace:
namespace Na {
class A;
namespace Nb {
class B {
...
friend class ::Na::A;
};
Without going from global top as 'friend class Na::A', the search will be done in Na::Nb::Na only.

Cpp Friend function has no access to private static members

I have a class with a private static variable. The main function should change the value in the variable, but even if I set the main function as a friend of the class the compiler tells me that the variable is private and not accessible from main.
Example:
ClassA.h:
namespace nameA{
class ClassA {
private:
static int varA;
public:
ClassA(){};
friend int main(void);
};
}
ClassA.cpp:
namespace nameA{
int ClassA::varA = 0;
}
main:
int main(void){
ClassA::varA = 42; //ERROR
}
I don't know if "friend" also allows access to static members or if I have to find another solution.
It because friend function main in ClassA is located in nameA namespace.
If you want to declare as friend the int main(void) function, that located in global scope, you should do it this way:
friend int ::main(void);
Whole source (compiled in VS2015):
int main(void);
namespace nameA {
class ClassA {
private:
static int varA;
public:
ClassA() {};
friend int ::main(void);
};
}
namespace nameA {
int ClassA::varA = 0;
}
int main(void) {
nameA::ClassA::varA = 42;
return 0;
}
Your friend declarations grants friendship to a function named main in the namespace nameA, not the global main function.
Your code is equivalent to
namespace nameA
{
int main(void);
class classA
{
...
friend int main(void);
};
}
You need to declare main before the namespace starts.
int main(void);
namespace nameA
{
class classA
{
...
friend int main(void);
};
}
should work

C++ private constructor (with argument) does not allow instantiation

I have a problem in my private constructor as below:
Lane.hpp:
namespace sim_mob
{
class B
{
friend class A;
private:
B(int){}
};
}
xmll.hpp:
#include"Lane.hpp"
namespace geo
{
class A
{
public:
A()
{
sim_mob::B b(2);
}
};
}
main.cpp:
#include"xmll.hpp"
int main()
{
geo::A a;
return 0;
}
command:
$ g++ main.cpp
In file included from main.cpp:2:0:
Lane.hpp: In constructor ‘geo::A::A()’:
Lane.hpp:10:5: error: ‘sim_mob::B::B(int)’ is private
xmll.hpp:9:23: error: within this context
The point is if I didn't have any arguments in the constructor, I wouldn't receive this error. May I Know why i am getting this and how to solve it?
many Thanks
In class sim_mob::B you befriend a class sim_mob:A but you hope that this friendship extends to geo::A which it, obviously, does not. To solve this you'd need a declaration of geo::A before making it a friend:
namespace geo { class A; }
namespace sim_mob
{
class B
{
friend class geo::A;
private:
B(int){}
};
}
The fact that it "works" with the default constructor is, I guess, that you rather declared a function than instantiate an object:
sim_mob::B b();
is a function declaration. If you leave off the parenthesis you should get an error about the default constructor not existing or, if you actually declare it, not being accessible.
Forward declare:
namespace geo{
class A;
}
In class B:
friend class geo::A;
friend class A; friends class A in the current namespace, i.e. sim_mob::A, not geo::A. You need to declare the class, and then use fully qualified name:
namespace bar { struct bar; }
namespace foo {
struct foo {
private:
friend struct bar::bar;
explicit foo(int) {}
};
}
namespace bar {
struct bar {
bar() { foo::foo x(42); }
};
}

Error Msg: Pure Abstract Class wrapped in a Namespace in C++

Need help with implementing a pure abstract class via inheritance, using namespace to wrap all my classes to avoid conflict with others.
I have been able to build and run the code successfully if I remove namespace wrapper from my abstract class and all classes that inherit from my pure abstract class.
It seems like Visual Studio 2010 compiler is complaining that despite all classes are in the same namespace, the abstract class's pure abstract method is not implemented.
Any help would be much appreciated.
//IBaseClass.h
//forward declaration
class ConcreteClass;
//namespace MyCustomNamespace
//{
class IBaseClass
{
public:
virtual ~IBaseClass() { /*virtual destructor*/ }
//Behaviours...
virtual bool Method001( const ConcreteClass &cc ) = 0;
//virtual bool Method002(/*some input*/) = 0;
};
//} /*NAMESPACE*/
//-----------------------------------------
//ParentClass.h
//namespace MyCustomNamespace
//{
class ParentClass : virtual public IBaseClass
{
private:
int a;
public:
virtual ~ParentClass() { /*virtual destructor*/ }
//getter-setter implemented in ParentClass.cpp file...
void setA(const int aa);
const int getA() const;
};
//} /*NAMESPACE*/
//-----------------------------------------
//ConcreteClass.h
//namespace MyCustomNamespace
//{
class ConcreteClass: public ParentClass
{
private:
int b;
public:
virtual ~ConcreteClass() { /*virtual destructor*/ }
//getter-setter...
void setB(const int bb);
const int getB() const;
bool Method001( const ConcreteClass &cc ); //re-declaring IBase abstract method...
};
//} /*NAMESPACE*/
//-----------------------------------------
//ConcreteClass.cpp
//namespace MyCustomNamespace
//{
void ConcreteClass::setB(const int bb) { this->b = bb; }
const int ConcreteClass::getB() const { return this->b; }
bool ConcreteClass::Method001( const ConcreteClass &cc )
{
//implementation code goes here...
return false;
}
//} /*NAMESPACE*/
The problem is that your forward class has been declared in another namespace (specifically, the global namespace). Thus, the virtual to override is a different symbol with a different parameter type.
As written, the compiler matches ConcreteClass to the forward declaration it sees in the global namespace when declared in the base:
virtual bool Method001( const ConcreteClass &cc ) = 0;
When you declare Method001 in ConcreteClass:
virtual bool Method001( const ConcreteClass &cc );
the compiler matches cc to MyCustomNamespace::ConcreteClass because that is a more accurate match.
To resolve the issue, just place your forward declaration in the proper namespace:
namespace MyCustomNamespace {
class ConcreteClass;
}

Friend function cannot access private function if class is under a namespace

I have a class inside a namespace and that class contains a private function. And there is a global function. I want that global function to be the friend of my class which is inside the namespace. But when I make it as a friend, the compiler thinks that the function is not global and it is inside that namespace itself. So if I try to access the private member function with global function, it doesn't work, whereas if I define a function with the same name in that namespace itself it works. Below is the code you can see.
#include <iostream>
#include <conio.h>
namespace Nayan
{
class CA
{
private:
static void funCA();
friend void fun();
};
void CA::funCA()
{
std::cout<<"CA::funCA"<<std::endl;
}
void fun()
{
Nayan::CA::funCA();
}
}
void fun()
{
//Nayan::CA::funCA(); //Can't access private member
}
int main()
{
Nayan::fun();
_getch();
return 0;
}
I also tried to make friend as
friend void ::fun();
And it also doesn't help.
You need to use the global scope operator ::.
void fun();
namespace Nayan
{
class CA
{
private:
static void funCA();
friend void fun();
friend void ::fun();
};
void CA::funCA()
{
std::cout<<"CA::funCA"<<std::endl;
}
void fun()
{
Nayan::CA::funCA();
}
}
void fun()
{
Nayan::CA::funCA(); //Can access private member
}
The fun() function is in the global namespace. You need a prototype:
void fun();
namespace Nayan
{
class CA
{
private:
static void funCA() {}
friend void ::fun();
};
}
void fun()
{
Nayan::CA::funCA();
}