Friend Class to access the protected virtual function in C++ - c++

I have three classes: Class A, Class B and Class C. Class B is derived from Class A. A protected pure virtual function declared in class A is defined in Class B. Class C is a friend function of Class A. Now I need to call that virtual function from class C. When I try to compile, I get the error as cannot access protected member declared in class A.
Isn't it possible?
Edit: Code added:
//A.h
class A
{
friend class C;
protected:
virtual int SetPtr(unsigned long long Offset)=0;
};
//B.h
class B: public A
{
protected:
int SetPtr(unsigned long long Offset) override;//function defined in B.cpp
};
//C.h
class C
{
public:
C(A& aObj);
int CallMyFun();
private:
A& obj;
};
//C.cpp:
C::C(A& aObj) :obj(aObj)
{
}
int C::CallMyFun()
{
obj.SetPtr(1);
return 0;
}

Related

Override virtual protected method that is a friend of another class

Basically, I want to somehow simulate friendship inheritance with the restriction that it can only happen from inside a certain method.
So essentially, this is what I want
class A; // Forward declaration
class Base{
friend class A; // friend declaration so that A is able to see protected methods
protected:
virtual void method() {// some definition, might also be pure virtual}
}
class Derived : public Base{
A aObj;
void method(){//override the one in base and also gain access to aObj private members.}
public:
//public interface
}
class A {
int var;
friend void Base::method();
public:
// public interface
}
is there anyway to achieve this?
How about this
class Base {
friend class A;
protected:
virtual void method() = 0;
std::tuple<int> GetAProperties(const A& a) {
// You can change the tuple params
// as per your requirement.
return std::make_tuple(a.var);
}
}
class Derived : public Base {
A aObj;
void method() override {
auto objProperties = GetAProperties(aObj);
}
}
You could get pointer to private's A member in Base, and then pass these member pointers to the Derived:
class A; // Forward declaration
class Base{
friend class A; // friend declaration so that A is able to see protected methods
private:
void method(A&);
virtual void do_method(A& a,int A::* var) {// some definition, might also be pure virtual
(a.*var)++;
}
};
class A{
int var;
friend void Base::method(A&);
};
class Derived : public Base{
A aObj;
virtual void do_method(A& a,int A::* var) {// some definition, might also be pure virtual
a.*var+=2;
}
public:
//public interface
};
void Base::method(A& a){
do_method(a,&A::var);
}
NB: do not use it on the critical pass!!

Can a virtual function access the friend of base class?

I am just a beginner in C++, my question is can a virtual function access the friend of base class? or the virtual function will only access the class's friend function in which it is defined?
class A
{
friend class B;
public:
virtual void setData();
};
now if a class is derived from class A
class C:public class A{
public:
setData()
{
//can I use the friend class B here?
}
};
First, you have friendship backwards. B is a friend of A, but that gives A zero extra rights over B.
In C++, friendship does not commute. A says B is a friend, but A may not be a friend of B.
Second, friendship is not inherited. You don't go out drinking with your mother's friends.
Third, there are many ways to republish or share rights. The class that is a friend can have a method that does the operation on the friend.
Suppose you really wanted this:
class B {
friend class A;
void doStuff();
};
class A {
public:
virtual void setData(B* b) = 0;
};
class C:public A{
public:
virtual void setData(B* b) {
b->do_stuff();
}
};
C::setData generates an error. But we can change it like this:
class A {
protected:
void do_stuff_on_b(B* b) { b->do_stuff(); }
public:
virtual void setData(B* b) = 0;
};
class C:public A{
public:
virtual void setData(B* b) {
do_stuff_on_b(b);
}
};
we could also generalize this and create an access token:
class B {
struct access_token{ explicit access_token(int) {} };
friend class A;
public:
void doStuff(access_token);
};
class A {
protected:
static B::access_token access_b() { return access_token(0); };
public:
virtual void setData(B* b) = 0;
};
class C:public A{
public:
virtual void setData(B* b) {
b->do_stuff( access_b() );
}
};
where we gatekeep access to B private methods based on possession of an access token that can be passed around. The methods are public, but the token itself can only be created by friends.

Access to specific private members from specific class

I have a class
class A
{
.....
private:
int mem1;
int mem2;
}
I have another class B which need to access only to mem1.
class B
{
....
}
How can I access private member mem1 from only from class B? I don't want to use friend. This means access to all private members.
With some rearrangement to class A (which might not necessarily be acceptable), you can achieve this:
class Base
{
friend class B;
int mem1;
};
class A : public Base
{
int mem2;
};
This exploits the fact that friendship is not transitive through inheritance.
Then, for class B,
class B
{
void foo(A& a)
{
int x = a.mem1; // allowed
int y = a.mem2; // not allowed
}
};
You can write a base class with member mem1 and friend B
class Base {
protected:
int mem1;
friend class B;
};
class A: private Base {
// ...
};

Pure Virtual Friend Class

I have class A that has a pointer to an instance of the pure virtual class B. Class C is derived from B and will automatically have a pointer to A (which is its parent), and needs to access its members. This can be achieved by adding friend class C inside class A, though then this is needed for every class that will derive from B.
Code example:
class A
{
public:
friend class B; // This does not allow derived classes to be friends
friend class C; // Now derived class B has access to `DoDomething`, but then this is needed for every single derived class
private:
void DoDomething();
};
class B
{
virtual void Tick() = 0;
protected:
A* m_pointerToA; // <- is being set upon creating automatically
};
class C : public class B
{
virtual void Tick()
{
m_pointerToA->DoSomething();
}
};
Is there a way to make all derived classes from B have access to private and protected members of class A that they are pointing to, without having to add friend class X for each of them?
Since friendship is not inherited, you need to wrap all the functionality that relies on friendship into protected functions of the base class B. This will let all classes deriving from B access the functionality of A that needs "befriending":
class B {
virtual void Tick() = 0;
protected:
A* m_pointerToA; // <- is being set upon creating automatically
void callDoSomething() {
m_pointerToA->DoSomething();
}
};
class C : public class B {
virtual void Tick() {
std::cout << "Class C is about to tick..." << std::endl;
callDoSomething();
}
};
class D : public class B {
virtual void Tick() {
callDoSomething();
std::cout << "Class D has just ticked!" << std::endl;
}
};
This effectively localizes the area where the friendship is used in your class hierarchy to class B, which helps with encapsulation.

function calling from a different class

Here is a skeleton code:
class C{
callMe(){}
};
class A{
// How to use callMe()
};
class B : C {
callMe();
A a;
};
In this example class B extends class C, so it can call callMe() method. But I need to use callMe() using class A given that class A can not extend class C. I wonder how?
you need to make A contain an object of type C.
class A
{
private:
C objC;
public:
void WhateverMethod() { objC.CallMe(); }
};
Also, the syntax for inheritance is
class B : C{
};
If you want B to simply have access to CallMe(), then you do not need to redefine it in B. It will inherit it from C. If you want B to override CallMe then you need to do this:
class C
{
public:
virtual void CallMe() { //definition }
};
class B : public C
{
public:
void CallMe() { //redefine it here }
};
Note, I assume from your syntax errors that you are a JAVA programmer. Methods are not automatically marked as virtual in C++, you have to mark them as virtual if you want to use polymorphism, and you have to use them from a pointer for it to work.
class C{
callMe(){}
friend class A;
};
class A{
//use call me here
};
You need to provide an instance of C:
class C {
public: // has to be public
void callMe() const {}
};
class A{
public:
A(const C& inst) : inst(inst) {}
void foo() {
inst.callMe();
}
private:
const C& inst;
};