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

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); }
};
}

Related

Predeclare subclasses [duplicate]

I recently got stuck in a situation like this:
class A
{
public:
typedef struct/class {…} B;
…
C::D *someField;
}
class C
{
public:
typedef struct/class {…} D;
…
A::B *someField;
}
Usually you can declare a class name:
class A;
But you can't forward declare a nested type, the following causes compilation error.
class C::D;
Any ideas?
You can't do it, it's a hole in the C++ language. You'll have to un-nest at least one of the nested classes.
class IDontControl
{
class Nested
{
Nested(int i);
};
};
I needed a forward reference like:
class IDontControl::Nested; // But this doesn't work.
My workaround was:
class IDontControl_Nested; // Forward reference to distinct name.
Later when I could use the full definition:
#include <idontcontrol.h>
// I defined the forward ref like this:
class IDontControl_Nested : public IDontControl::Nested
{
// Needed to make a forwarding constructor here
IDontControl_Nested(int i) : Nested(i) { }
};
This technique would probably be more trouble than it's worth if there were complicated constructors or other special member functions that weren't inherited smoothly. I could imagine certain template magic reacting badly.
But in my very simple case, it seems to work.
If you really want to avoid #including the nasty header file in your header file, you could do this:
hpp file:
class MyClass
{
public:
template<typename ThrowAway>
void doesStuff();
};
cpp file
#include "MyClass.hpp"
#include "Annoying-3rd-party.hpp"
template<> void MyClass::doesStuff<This::Is::An::Embedded::Type>()
{
// ...
}
But then:
you will have to specify the embedded type at call time (especially if your function does not take any parameters of the embedded type)
your function can not be virtual (because it is a template)
So, yeah, tradeoffs...
I would not call this an answer, but nonetheless an interesting find:
If you repeat the declaration of your struct in a namespace called C, everything is fine (in gcc at least).
When the class definition of C is found, it seems to silently overwrite the namspace C.
namespace C {
typedef struct {} D;
}
class A
{
public:
typedef struct/class {...} B;
...
C::D *someField;
}
class C
{
public:
typedef struct/class {...} D;
...
A::B *someField;
}
If you have access to change the source code of classes C and D, then you can take out class D separately, and enter a synonym for it in class C:
class CD {
};
class C {
public:
using D = CD;
};
class CD;
This would be a workaround (at least for the problem described in the question -- not for the actual problem, i.e., when not having control over the definition of C):
class C_base {
public:
class D { }; // definition of C::D
// can also just be forward declared, if it needs members of A or A::B
};
class A {
public:
class B { };
C_base::D *someField; // need to call it C_base::D here
};
class C : public C_base { // inherits C_base::D
public:
// Danger: Do not redeclare class D here!!
// Depending on your compiler flags, you may not even get a warning
// class D { };
A::B *someField;
};
int main() {
A a;
C::D * test = a.someField; // here it can be called C::D
}
This can be done by forward declare the outer class as a namespace.
Sample: We have to use a nested class others::A::Nested in others_a.h, which is out of our control.
others_a.h
namespace others {
struct A {
struct Nested {
Nested(int i) :i(i) {}
int i{};
void print() const { std::cout << i << std::endl; }
};
};
}
my_class.h
#ifndef MY_CLASS_CPP
// A is actually a class
namespace others { namespace A { class Nested; } }
#endif
class MyClass {
public:
MyClass(int i);
~MyClass();
void print() const;
private:
std::unique_ptr<others::A::Nested> _aNested;
};
my_class.cpp
#include "others_a.h"
#define MY_CLASS_CPP // Must before include my_class.h
#include "my_class.h"
MyClass::MyClass(int i) :
_aNested(std::make_unique<others::A::Nested>(i)) {}
MyClass::~MyClass() {}
void MyClass::print() const {
_aNested->print();
}

Opposite of friend declaration

Say we have a class that has a private constructor, through friend we can allow some specific class(es) to still create objects of this class:
class Foo
{
friend class Bar;
private:
Foo();
};
class Bar
{
Bar()
{
//create a Foo object
}
};
Now what if I want the opposite of friend, where Foo looks like this:
class Foo
{
//enemy/foe??? class Bar; (if only)
public:
Foo();
};
And then no method of Bar can access the Foo constructor/ make an object of Foo but other classes can (because it's public).
class Bar
{
Bar()
{
Foo foo; //compiler error
}
};
Is such a construct possible or am I stuck with keeping Foo private and adding friends for all the classes?
Such a thing does not exist, and it would be extremely pointless. Imagine you have a situation like this:
class Foo
{
enemy class Bar;
public:
Foo() {}
};
class Bar
{
void evil() { Foo{}; }
};
Nothing prevents the implementor of Bar from doing this:
class Bar
{
void evil() { do_evil(*this); }
};
void do_evil(Bar &self)
{
Foo{};
}
do_evil is not a member of Bar (it's a global function), and so it's not an enemy. Such non-friendliness could therefore be trivially circumvented.
It cannot be done really, but maybe following is enough for you:
template <typename T> struct Tag {};
class Foo
{
public:
template <typename T>
Foo(Tag<T>) {}
Foo(Tag<Bar>) = delete;
// ...
};
And so asking "creator" to "identify" itself.
class Bar
{
Bar()
{
Foo foo{Tag<Bar>{}}; //compiler error
// Foo foo{Tag<void>{}}; // valid as we can cheat about identity.
}
};
There is no such concept in C++.
Public attributes will always be public, but you can limit the exposure of Foo by making the constructor protected, for instance, and only visible for selected classes (although limiting friend is advised). Perhaps also make Foo as a protected class of Bar2 because only Bar2 or its children will actually use it.
As it has already been sayed by others, your desire breaks the idea of encapsulation because you cannot always know who your enemies are.
But, still, there is a possibility to get (almost) what you want:
#include <type_traits>
struct enemy; // We need a forward declaration of your enemy
struct my_class {
// The access is done using a factory, where the caller has to tell
// us his own name
template <class T>
struct make{
static_assert(!std::is_same<T,enemy>::value,"you are my enemy.");
friend T;
private:
my_class operator() () { return my_class{}; }
};
private:
my_class(); // This is the constructor we care about
};
struct no_enemy {
void bar() {
my_class a = my_class::make<no_enemy>{}(); // works
}
};
struct enemy {
void bar() {
my_class b = my_class::make<enemy>{}(); // error: static_assert failed
my_class c = my_class::make<no_enemy>{}(); // error: foo is "private"
}
};

Forward declaration of nested struct [duplicate]

I recently got stuck in a situation like this:
class A
{
public:
typedef struct/class {…} B;
…
C::D *someField;
}
class C
{
public:
typedef struct/class {…} D;
…
A::B *someField;
}
Usually you can declare a class name:
class A;
But you can't forward declare a nested type, the following causes compilation error.
class C::D;
Any ideas?
You can't do it, it's a hole in the C++ language. You'll have to un-nest at least one of the nested classes.
class IDontControl
{
class Nested
{
Nested(int i);
};
};
I needed a forward reference like:
class IDontControl::Nested; // But this doesn't work.
My workaround was:
class IDontControl_Nested; // Forward reference to distinct name.
Later when I could use the full definition:
#include <idontcontrol.h>
// I defined the forward ref like this:
class IDontControl_Nested : public IDontControl::Nested
{
// Needed to make a forwarding constructor here
IDontControl_Nested(int i) : Nested(i) { }
};
This technique would probably be more trouble than it's worth if there were complicated constructors or other special member functions that weren't inherited smoothly. I could imagine certain template magic reacting badly.
But in my very simple case, it seems to work.
If you really want to avoid #including the nasty header file in your header file, you could do this:
hpp file:
class MyClass
{
public:
template<typename ThrowAway>
void doesStuff();
};
cpp file
#include "MyClass.hpp"
#include "Annoying-3rd-party.hpp"
template<> void MyClass::doesStuff<This::Is::An::Embedded::Type>()
{
// ...
}
But then:
you will have to specify the embedded type at call time (especially if your function does not take any parameters of the embedded type)
your function can not be virtual (because it is a template)
So, yeah, tradeoffs...
I would not call this an answer, but nonetheless an interesting find:
If you repeat the declaration of your struct in a namespace called C, everything is fine (in gcc at least).
When the class definition of C is found, it seems to silently overwrite the namspace C.
namespace C {
typedef struct {} D;
}
class A
{
public:
typedef struct/class {...} B;
...
C::D *someField;
}
class C
{
public:
typedef struct/class {...} D;
...
A::B *someField;
}
If you have access to change the source code of classes C and D, then you can take out class D separately, and enter a synonym for it in class C:
class CD {
};
class C {
public:
using D = CD;
};
class CD;
This would be a workaround (at least for the problem described in the question -- not for the actual problem, i.e., when not having control over the definition of C):
class C_base {
public:
class D { }; // definition of C::D
// can also just be forward declared, if it needs members of A or A::B
};
class A {
public:
class B { };
C_base::D *someField; // need to call it C_base::D here
};
class C : public C_base { // inherits C_base::D
public:
// Danger: Do not redeclare class D here!!
// Depending on your compiler flags, you may not even get a warning
// class D { };
A::B *someField;
};
int main() {
A a;
C::D * test = a.someField; // here it can be called C::D
}
This can be done by forward declare the outer class as a namespace.
Sample: We have to use a nested class others::A::Nested in others_a.h, which is out of our control.
others_a.h
namespace others {
struct A {
struct Nested {
Nested(int i) :i(i) {}
int i{};
void print() const { std::cout << i << std::endl; }
};
};
}
my_class.h
#ifndef MY_CLASS_CPP
// A is actually a class
namespace others { namespace A { class Nested; } }
#endif
class MyClass {
public:
MyClass(int i);
~MyClass();
void print() const;
private:
std::unique_ptr<others::A::Nested> _aNested;
};
my_class.cpp
#include "others_a.h"
#define MY_CLASS_CPP // Must before include my_class.h
#include "my_class.h"
MyClass::MyClass(int i) :
_aNested(std::make_unique<others::A::Nested>(i)) {}
MyClass::~MyClass() {}
void MyClass::print() const {
_aNested->print();
}

C++ struct declaration in class [duplicate]

I recently got stuck in a situation like this:
class A
{
public:
typedef struct/class {…} B;
…
C::D *someField;
}
class C
{
public:
typedef struct/class {…} D;
…
A::B *someField;
}
Usually you can declare a class name:
class A;
But you can't forward declare a nested type, the following causes compilation error.
class C::D;
Any ideas?
You can't do it, it's a hole in the C++ language. You'll have to un-nest at least one of the nested classes.
class IDontControl
{
class Nested
{
Nested(int i);
};
};
I needed a forward reference like:
class IDontControl::Nested; // But this doesn't work.
My workaround was:
class IDontControl_Nested; // Forward reference to distinct name.
Later when I could use the full definition:
#include <idontcontrol.h>
// I defined the forward ref like this:
class IDontControl_Nested : public IDontControl::Nested
{
// Needed to make a forwarding constructor here
IDontControl_Nested(int i) : Nested(i) { }
};
This technique would probably be more trouble than it's worth if there were complicated constructors or other special member functions that weren't inherited smoothly. I could imagine certain template magic reacting badly.
But in my very simple case, it seems to work.
If you really want to avoid #including the nasty header file in your header file, you could do this:
hpp file:
class MyClass
{
public:
template<typename ThrowAway>
void doesStuff();
};
cpp file
#include "MyClass.hpp"
#include "Annoying-3rd-party.hpp"
template<> void MyClass::doesStuff<This::Is::An::Embedded::Type>()
{
// ...
}
But then:
you will have to specify the embedded type at call time (especially if your function does not take any parameters of the embedded type)
your function can not be virtual (because it is a template)
So, yeah, tradeoffs...
I would not call this an answer, but nonetheless an interesting find:
If you repeat the declaration of your struct in a namespace called C, everything is fine (in gcc at least).
When the class definition of C is found, it seems to silently overwrite the namspace C.
namespace C {
typedef struct {} D;
}
class A
{
public:
typedef struct/class {...} B;
...
C::D *someField;
}
class C
{
public:
typedef struct/class {...} D;
...
A::B *someField;
}
If you have access to change the source code of classes C and D, then you can take out class D separately, and enter a synonym for it in class C:
class CD {
};
class C {
public:
using D = CD;
};
class CD;
This would be a workaround (at least for the problem described in the question -- not for the actual problem, i.e., when not having control over the definition of C):
class C_base {
public:
class D { }; // definition of C::D
// can also just be forward declared, if it needs members of A or A::B
};
class A {
public:
class B { };
C_base::D *someField; // need to call it C_base::D here
};
class C : public C_base { // inherits C_base::D
public:
// Danger: Do not redeclare class D here!!
// Depending on your compiler flags, you may not even get a warning
// class D { };
A::B *someField;
};
int main() {
A a;
C::D * test = a.someField; // here it can be called C::D
}
This can be done by forward declare the outer class as a namespace.
Sample: We have to use a nested class others::A::Nested in others_a.h, which is out of our control.
others_a.h
namespace others {
struct A {
struct Nested {
Nested(int i) :i(i) {}
int i{};
void print() const { std::cout << i << std::endl; }
};
};
}
my_class.h
#ifndef MY_CLASS_CPP
// A is actually a class
namespace others { namespace A { class Nested; } }
#endif
class MyClass {
public:
MyClass(int i);
~MyClass();
void print() const;
private:
std::unique_ptr<others::A::Nested> _aNested;
};
my_class.cpp
#include "others_a.h"
#define MY_CLASS_CPP // Must before include my_class.h
#include "my_class.h"
MyClass::MyClass(int i) :
_aNested(std::make_unique<others::A::Nested>(i)) {}
MyClass::~MyClass() {}
void MyClass::print() const {
_aNested->print();
}

How to access private member function using friend class object?

In main, I want to access the display function. Here, in class B I declared class A as friend. So i thought that it is possible to access the private member functions.
But i dont know how to do that.
#include<stdio.h>
class A
{
public:
class B
{
public:
friend class A;
private:
void display()
{
printf("\nHi");
}
};
};
int main()
{
//here i wanna access display function.. is it possible?
return 1;
}
friend specifies what has access to private members. In your case, you want to access private members in the main function, so you should specify that it's friend:
class A
{
public:
class B
{
friend int main();
void display()
{
printf("\nHi");
}
};
};
int main()
{
// here you can access display function:
A::B object;
object.display();
}
Alternatively, if you want to make class A (and not anything else) a friend, then class A should access the display function. Any member of class A can do it:
class A
{
public:
class B
{
friend class A;
void display()
{
printf("\nHi");
}
};
// here you can access display function:
void access_display(B object)
{
object.display();
}
};
int main()
{
A object1;
A::B object2;
object1.access_display(object2);
}