I have problem with my class/pointers.
I have two classes FirstClass and SecondClass.
FirstClass has two pointers:
MyClass *character1;
MyClass *character2;
I assign to these pointers later in my code but now i have my SecondClass where i also have 2 pointers:
MyClass *oldChar1;
MyClass *oldChar2;
I want to set oldChar to the same as indicated by character. I made a function in SecondClass with friend clause in FirstClass.
void SecondClass::setChars()
{
*oldChar1 = FirstClass::character1;
*oldChar2 = FirstClass::character2;
}
Result:
illegal reference to non-static member 'FirstClass::character1'
I dont get it :/ Somebody can help me??
There are a few approaches to do this.
A friend function shared in both classes (source).
The friend function has access to the data members of the class MyFirstClass and MySecondClass, but the friend function still needs to be told which instances of those classes to use (see this) e.g.
class MyClass {
};
class MySecondClass; //forward declaration for later
class MyFirstClass {
private:
MyClass *character1;
MyClass *character2;
public:
//friend function
friend void setChars(MyFirstClass& c1, MySecondClass& c2); //<---- friend function
};
class MySecondClass {
private:
MyClass *oldChar1;
MyClass *oldChar2;
public:
//friend function
friend void setChars(MyFirstClass& c1, MySecondClass& c2);
};
//define the friend function
void setChars(MyFirstClass& c1, MySecondClass& c2) {
c2.oldChar1 = c1.character1;
c2.oldChar2 = c1.character2;
}
int main() {
MyFirstClass c1;
MySecondClass c2;
setChars(c1,c2);
}
Friend Class.
Make MySecondClass a friend of MyFirstClass. MySecondClass will have method setChars which will take an instance of MyFirstClass as a parameter. e.g.
class MyClass {
};
class MySecondClass;
class MyFirstClass {
private:
MyClass *character1;
MyClass *character2;
public:
friend MySecondClass; //<----- friend class
};
class MySecondClass {
private:
MyClass *oldChar1;
MyClass *oldChar2;
public:
void setCharsUsingFriendClass(MyFirstClass& c1) {
oldChar1 = c1.character1;
oldChar2 = c1.character2;
}
};
int main() {
MyFirstClass c1;
MySecondClass c2;
c2.setCharsUsingFriendClass(c1);
}
And finally using 2 getter methods. I think this approach is better because it allows the classes to hide their implementation details (encapsulation).
class MyClass {
};
class MySecondClass;
class MyFirstClass {
private:
MyClass *character1;
MyClass *character2;
public:
//define getters to access the private members
MyClass* GetCharacter1() {return character1;}
MyClass* GetCharacter2() {return character2;}
};
class MySecondClass {
private:
MyClass *oldChar1;
MyClass *oldChar2;
public:
void setCharsUsingGetters(MyFirstClass& c1) {
oldChar1 = c1.GetCharacter1();
oldChar2 = c1.GetCharacter2();
}
};
int main() {
MyFirstClass c1;
MySecondClass c2;
c2.setCharsUsingGetters(c1);
}
Related
I have two classes with name firstClass and secondClass. I managed to make the secondClass friend to firstClass. I am now trying to make only the secondClass constructor as a friend and not the entire class. First I get the error: ‘secondClass’ does not name a type and trying to fix it with forward declaration gives error: invalid use of incomplete type ‘class secondClass'.
Is it possible to make secondClass contructor as a friend to first class.
#include <iostream>
using namespace std;
/*
//these forward declaration, do not solve the problem
class firstClass;
class secondClass;
secondClass::secondClass(const firstClass& fc);
*/
class firstClass
{
private:
int value;
friend secondClass::secondClass(const firstClass& fc);
//friend class secondClass; //this works
public:
firstClass(int val = 0): value(val){}
};
class secondClass
{
public:
secondClass(int val = 0): value(val){}
secondClass(const firstClass& fc)
{
value = fc.value;
}
int getValue()
{
return value;
}
int value;
};
int main()
{
firstClass fc(5);
secondClass sc(fc);
cout<<sc.value;
}
Here's the proper way to do the forward declarations:
//secondClass needs to know the type firstClass exists to take it as an argument to the ctor
class firstClass;
class secondClass
{
public:
secondClass(int val = 0): value(val){}
secondClass(const firstClass& fc); //Just declare that this function exists
int getValue()
{
return value;
}
int value;
};
class firstClass
{
private:
int value;
//Since this function is declared, this works
friend secondClass::secondClass(const firstClass& fc);
public:
firstClass(int val = 0): value(val){}
};
//Finally, now that firstClass is implemented, we can implement this function
secondClass::secondClass(const firstClass& fc)
{
value = fc.value;
}
See it run here: https://ideone.com/ZvXIpw
Let's have a class A which has an inner class A::Impl. A class AllowedToAccess should be able to get A::Impl& from class A, no other class should be able to do that or even know that class A::Impl exists.
class A_1
{
public:
class Impl;
Impl& impl();
const Impl& impl() const;
private:
std::unique_ptr<Impl> m_impl;
};
class A_2
{
private:
friend class AllowedToAccess;
class Impl;
std::unique_ptr<Impl> m_impl;
};
class A_3
{
private:
friend class AllowedToAccess;
class Impl;
class ImplContainer
{
friend class A_3;
std::unique_ptr<Impl> impl;
} m_implContainer;
Impl& impl(); // return *m_implContainer.impl;
const Impl& impl() const; // return *m_implContainer.impl;
};
Here is some code to illustrate my ideas.
A_1
Pros: m_impl is secured.
Cons: classes not supposed to know about A::Impl will know about it (although they don't know what A::Impl really is about).
A_2
Pros: classes not supposed to know about A::Impl will not know about it.
Cons: m_impl is not secured (AllowedToAccess might just set it to nullptr).
A_3
Pros: classes not supposed to know about A::Impl will not know about it and m_impl is secured.
Cons: Boilerplate code for ImplContainer.
Any better ideas?
EDIT: Came up with a solution like this.
template <typename T>
class Accessor
{
private:
friend class AllowedToAccess;
typedef typename T::Impl impl_t;
static typename T::Impl& impl(T& t)
{
return *t.m_impl;
}
static const typename T::Impl& impl(const T& t)
{
return *t.m_impl;
}
};
class A
{
private:
friend class Accessor<A>;
class Impl;
std::unique_ptr<Impl> m_impl;
};
class A::Impl
{
public:
void f() const
{
}
};
class AllowedToAccess
{
public:
AllowedToAccess()
{
const A a;
const Accessor<A>::impl_t& impl = Accessor<A>::impl(a);
impl.f();
}
};
There is an implementation layer of code, and all those classes will be added as friends to Accessor.
And to further hide things the accessor would only be forward declared as template <typename T> class Accessor; in public code. And defined in private code.
If it is possible to move all logic that works with m_impl itself to a base class, you can make m_impl inaccessible to a derived class, but allow it to get a refernce to Impl, and then make Access class a friend of a derived class:
class Base {
protected:
class Impl;
Impl& impl();
private:
std::unique_ptr<Impl> m_impl;
};
class Base::Impl {
public:
Impl() {}
};
Base::Impl& Base::impl() { return *m_impl; }
class Derived : private Base {
public:
friend class Access;
Derived() {
auto& ptr = impl(); // ok
auto& ptr1 = m_impl; // error
}
};
class Access {
public:
Access(Derived& d) {
auto& ptr = d.impl(); // ok
auto& ptr1 = d.m_impl; // error
}
};
I don't know if its a better idea, but you could provide your own implementation of AllowedToAccess, that would safely expose needed interface. I call it Accessor.
class Base{
double priv = 0;
public:
friend class Accessor;
};
class Accessor {
public:
int& priv(Base& b) { return b.priv; };
};
Now classes can access exposed privates through Accessor. The semantics change a bit though because you use it like accessor.priv(b) = something but you have full control over the exposed interface. I think Accessor in this variation could have all static methods since the accessed object is passed always anyways. So the semantics would be Accessor::priv(b).
I guess it is a variation of your A_3 example, with code moved into the friend class. But it does not pollute A_ class.
Another option would be to provide your own Accessor class in form of a simple wrapper.
class Accessor {
public:
Accessor(Base b) _b(b);
int priv() { return _b.priv; };
int priv(int val) { _b.priv = val; };
int& priv_r() { return _b.priv; };
private:
Base& _b;
};
The interface here is also fully customizable, and you can access features like:
Base b;
Accessor interface(b);
interface.priv(42);
You can also make it absolutely safe disallowing to derive from Accessor (there are tricks for that), so no-one can derive and screw up your objects via an evil implementation of the Accessor. I think it would be a little bit paranoid though.
How about this:
class A_4
{
public:
class Impl;
Impl& impl();
const Impl& impl() const;
private:
std::unique_ptr<Impl> m_impl;
};
class A_4::Impl
{
private:
friend class A_4;
friend class AllowedToAccess;
Impl();
~Impl();
Impl(const Impl&) = delete;
Impl& operator=(const Impl&) = delete;
// All members private!
};
It doesn't matter that code can call impl() or write A_4::Impl if there's nothing useful they can actually do with it.
I obtain a error: 'func' does not name a type when a member function func of a class B attempts to return a class C:
class A {
public:
class B {
public:
C func() const {
...
}
private:
friend class A;
}
class C {
public:
...
private:
friend class A;
}
private:
...
}
Whereas, if func is a member function of A, then the following does not produce this error:
class A {
public:
class B {
public:
...
private:
friend class A;
}
C func() const {
...
}
class C {
public:
...
private:
friend class A;
}
private:
...
}
How can I fix it to make the first version work?
I found a great example here.
Define class C "above" class B, or forward declare it.
I was wondering how you would call a getter function from another class in another class. For example what I have right now is not working
class A{
public:
friend class B;
std::string getfirst(){ return b.getfirst();}
private:
B b;
};
class B{
public:
std::string getfirst(){
return first_;
}
private:
std::string first_;
};
How would I fix this so that I can call B's getfirst function?
You do not need friendship.
What about?
class B {
public:
std::string get_first() const { return first_; }
private:
std::string first_;
};
class A {
public:
std::string get_first() const { return b.get_first(); }
private:
B b;
};
Now, class B has a getter for its first and class A has getter that delegates to b member variable.
class B{
public:
std::string getfirst(){
return first_;
}
private:
std::string first_;
};
class A : public B{
public:
//class A has derived the "getfirst" from B
private:
// add your stuff here
};
did not compile it,but should work fine
The code you have has an error: std::string getfirst(){ is repeated twice in B, this will cause a compilation error.
Also, you do not need to declare B as friend of A, as B is not trying to access any of A's private members. Ignore this if you have a larger code where you do need the friend declaration.
You need to define class B before using using it in A. As B does not access A, you can just put its definition before A's.
This is really wierd
std::string getfirst(){
std::string getfirst(){
return first_; //cause compilation error
It may correct as:
#include <iostream>
using namespace std;
class B; // Forward declaration of class B in order for example to compile
class A
{
public:
string getfirst();
friend string :: getfirst(); // declaration of global friend
};
class B
{
public:
friend string :: getfirst(); // declaration of global friend
friend string A::getfirst(); // declaration of friend from other class
};
I am giving skeleton only.
In C++, I have a class A, and a class B.
In class A, there is a object (of class B) , I want to change the class A member data in the object of class B. How can I do that ?
I want to do this:
class A {
public:
A() {
new B(this);
}
private:
int i;
};
class B {
public:
B(A* parent) {
this->parent = parent;
}
change() {
parent->i = 5;
}
private:
A* parent;
};
In declaration of class A you need to define class B as a friend:
friend class B;
Rather than setting B as a friend class to A, a better method to preserve encapsulation would be to add a setter method to class A.
Your class A would then look somewhat like this:
class A {
public:
A() {
new B(this);
}
void set_i(int value)
{
i = value;
}
private:
int i;
};
Then in your class B implementation, call set_i().
class B {
public:
B(A* parent) {
this->parent = parent;
}
change() {
parent->set_i(5);
}
private:
A* parent;
};
This way you're not exposing and relying on private implementation details of class A in class B.
class A {
friend class B;
private:
int i;
public:
A() : i(0) {
new B(this);
}
};