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.
Related
I am not sure if I am doing this right, but how do I give the class definition of the following class node here for a list with and without a friend class? In which one do I use private: or public:?
Without friend class:
class node {
public:
el_t Elm;
Node *Next;
}
With friend class:
class node {
private:
el_t Elem;
Node* Next;
}
friend is a specifier that grants specific function or the whole class itself access to its protected as well as private members and methods:
class SomeFriend;
class SomeClass
{
public:
SomeClass(int a, int b, int c) : a_(a), b_(b), c_(c) {}
virtual ~SomeClass();
private:
int a_, b_, c_;
friend SomeFriend;
};
class SomeFriend
{
public:
virtual ~SomeFriend();
int AddABC(SomeClass& b) { return b.a_ + b.b_ + b.c_; }
};
What is its difference from inheritance, then?
friend members require an external instance of the base class to access its members, while a derived class is already itself an instance of the base class...
What else can be improved in the above code?
You could move the declaration of the class SomeFriend above SomeClass... and just do:
class SomeClass;
class SomeFriend
{
public:
virtual ~SomeFriend();
int AddABC(SomeClass& b);
};
class SomeClass
{
public:
SomeClass(int a, int b, int c) : a_(a), b_(b), c_(c) {}
virtual ~SomeClass();
private:
int a_, b_, c_;
// Making only the member function 'AddABC' friend of this class...
friend int SomeFriend::AddABC(SomeClass& b);
};
int SomeFriend::AddABC(SomeClass& b)
{
return b.a_ + b.b_ + b.c_;
}
Here, you don't make the class the friend, but the specific function that only requires its private and protected members...
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!!
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;
}
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;
};
I ran into an error yesterday and, while it's easy to get around, I wanted to make sure that I'm understanding C++ right.
I have a base class with a protected member:
class Base
{
protected:
int b;
public:
void DoSomething(const Base& that)
{
b+=that.b;
}
};
This compiles and works just fine. Now I extend Base but still want to use b:
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
b+=that.b;
d=0;
}
};
Note that in this case DoSomething is still taking a reference to a Base, not Derived. I would expect that I can still have access to that.b inside of Derived, but I get a cannot access protected member error (MSVC 8.0 - haven't tried gcc yet).
Obviously, adding a public getter on b solved the problem, but I was wondering why I couldn't have access directly to b. I though that when you use public inheritance the protected variables are still visible to the derived class.
A class can only access protected members of instances of this class or a derived class. It cannot access protected members of instances of a parent class or cousin class.
In your case, the Derived class can only access the b protected member of Derived instances, not that of Base instances.
Changing the constructor to take a Derived instance will solve the problem.
protected members can be accessed:
through this pointer
or to the same type protected members even if declared in base
or from friend classes, functions
To solve your case you can use one of last two options.
Accept Derived in Derived::DoSomething or declare Derived friend to Base:
class Derived;
class Base
{
friend class Derived;
protected:
int b;
public:
void DoSomething(const Base& that)
{
b+=that.b;
}
};
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
b+=that.b;
d=0;
}
};
You may also consider public getters in some cases.
As mentioned, it's just the way the language works.
Another solution is to exploit the inheritance and pass to the parent method:
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
Base::DoSomething(that);
d=0;
}
};
You have access to the protected members of Derived, but not those of Base (even if the only reason it's a protected member of Derived is because it's inherited from Base)
You can try with static_cast< const Derived*>(pBase)->Base::protected_member ...
class Base
{
protected:
int b;
public:
...
};
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
b += static_cast<const Derived*>(&that)->Base::b;
d=0;
}
void DoSomething(const Base* that)
{
b += static_cast<const Derived*>(that)->Base::b;
d=0;
}
};
class Derived : public Base
{
protected:
int d;
public:
void DoSomething()
{
b+=this->b;
d=0;
}
};
//this will work
Following the hack for stl I wrote a small code which seems to solve the problem of accessing the protected members in derived class
#include <iostream>
class B
{
protected:
int a;
public:
void dosmth()
{
a = 4;
}
void print() {std::cout<<"a="<<a<<std::endl;}
};
class D: private B
{
public:
void dosmth(B &b)
{
b.*&D::a = 5;
}
};
int main(int argc, const char * argv[]) {
B b;
D d;
b.dosmth();
b.print();
d.dosmth(b);
b.print();
return 0;
}
Prints
a=4
a=5
Use this pointer to access protected members
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
this->b+=that.b;
d=0;
}
};