c++ derived base class Friend function accessing private on Parent? - c++

Please consider the scenario below:
class A
{
friend void B::Itemfunction();
private:
int number;
int size;
public:
Randomfunction();
}
class B : public A
{
private:
string Random;
public:
void Itemfunction();
void CheckLog();
}
Would it be possible for an object made in Itemfunction of type A to access the private data members of obj? Such as:
void B::Itemfunction(){
A obj;
//Possible to do...
obj.number = 2;
}
I understand that the derived class B can access all the public parts of A, but if I wanted just one function (Itemfunction) to access the private parts would this be the correct way of doing it? I just want to see if my understanding is correct.
Cheers

No, it's not possible. You cannot friend a class member function for a class that isn't yet completely declared.
The only way in that case (since class B needs a completely declared class A to inherit), is to forward declare class B; and friend the whole class:
#include <iostream>
#include <string>
class B;
class A
{
// friend void B::Itemfunction();
friend class B;
private:
int number;
int size;
public:
void Randomfunction();
};
class B : public A
{
private:
std::string Random;
public:
void Itemfunction();
void CheckLog();
};
int main()
{
}
Live Demo

In your code, where you implement Itemfunction, you are creating a new, completely unrelated object of type A locally. In inheritance, your B object has an internal subobject of type A. You can access the fields of A directly within B. However, you can't access private members. Your friendship trick will not work; you cannot declare a method of B a friend until you see Bs definition, but B can't be defined until A is defined, and as you can see we're going in circles. What you can do instead is to make that member protected:
class A
{
protected:
int number;
private:
int size;
public:
Randomfunction();
}
void B::Itemfunction() {
number = 2;
}

This has a chicken and egg problem. Both B must be fully defined for A to see B::Itemfunction.
class A
{
friend void B::Itemfunction(); <-- Itemfunction does not exist yet
private:
int number;
int size;
public:
int Randomfunction();
};
class B: public A
{
private:
std::string Random;
public:
void Itemfunction();
void CheckLog();
};
Swapping the order won't work either because B needs A to be defined to inherit from A.
class B: public A <-- A does not exist yet
{
private:
std::string Random;
public:
void Itemfunction();
void CheckLog();
};
class A
{
friend void B::Itemfunction();
private:
int number;
int size;
public:
int Randomfunction();
};
Solution 1 is forward define class B so the compiler knows that B exists, even if it knows nothing about it, and then friend the whole class, because A only knows B exists. OP's friend relationship is maintained.
class B; <-- forward definition of B
class A
{
friend class B; <-- friending all of B, not just the function
private:
int number;
int size;
public:
int Randomfunction();
};
class B: public A
{
private:
std::string Random;
public:
void Itemfunction();
void CheckLog();
};
BUT! All of B now has complete access to all of A. If A wants to keep size or any other members hidden and under it's control, tough. B can call all of A's functions and change all of A's member variables. B can totally pown A.
This also doesn't scale to other subclasses. B can see all of A, but C and D cannot.
So say you have a less trivial example where A cannot allow anyone to mess with the value of size. Maybe it's the capacity of an internal array, and changing size will result in A running past the end of allocated memory. The reason doesn't matter much here; for the sake of this example no one but A is allowed to change size.
This leads us to solution 2: protected access and accessor functions.
class A
{
protected: <-- all inheritors can access members in this block. No one else can
int number;
private: <-- only A can access members in this block
int size;
public:
int Randomfunction();
int getSize() <-- accessor function to provide read-only access to size
{
return size;
}
};
class B: public A
{
private:
std::string Random;
public:
void Itemfunction(); <-- can do anything to number and read size
void CheckLog(); <-- so can this
};
class C: public A
{
private:
std::string member;
public:
void doStuff(); <-- and this
void DoOtherStuff(); <-- and this
};
B and C can access A::number and can use A::getSize to see the value of size. number can be changed by B and C, but size cannot. If you are worried about the cost of calling a function to read size, don't be. When the compiler is done with A::getSize, you won't even know it's there. It probably isn't.

Related

Why Friend Function cannot access private members of a class

class A{
public:
void printer(){
B obj;
obj.private_data = 10; // <- fails, says member inaccessible
}
}
class B{
friend void A::printer();
private:
int private_data;
}
is it possible for printer function to access private members of class B? i tried to pass an obj of B as arg to printer but it still failed
Class A doesn't know about B to use it. Hence, postpone the definition of the function printer() until you define B, and if you need an instance of B to be a member var in A then make a forward declaration for B to declare a B* in A.
Hence, use something like what follows:
class A {
public:
void printer();
};
class B {
friend void A::printer();
private:
int private_data;
};
void A::printer() {
B obj;
obj.private_data = 10; // <- No longer fails
std::cout << obj.private_data;
}
int main() {
A a;
a.printer();
}
Demo
Why Friend Function cannot access private members of a class?
They can, but you may need to split the definition of the class up a bit.
Imaginary files added:
Define A (file a.hpp):
class A {
public:
void printer();
};
Define B (file b.hpp):
#include "a.hpp" // B must see the definition of A to befriend a member function
class B {
friend void A::printer();
private:
int private_data;
};
Define A's member function (file a.cpp):
void A::printer() {
B obj;
obj.private_data = 10;
}
To access B, you first need to define it. Thus, you can just declare the method printer and define it after you have defined the class B.
class A {
public:
void printer();
};
class B {
private:
friend class A;
int private_data;
};
void A::printer() {
B obj;
obj.private_data = 10;
}
Note, you probably want to move your methods out of your class definition anyways and into a separate .cpp file. Methods defined inside the class are implicitly marked as inline which might not be what you expect.

Output of program in inheritance

I was learning about inheritance. If we have used private access specifier in base class then it is not accessible in derived class.
But I have a doubt regarding this.
#include<bits/stdc++.h>
using namespace std;
class A
{
private:
int a;
int b;
int c;
public:
int d;
void print()
{
cout<<"Inside A Print()"<<endl;
}
};
class B: public A
{
private:
int a1,b1,c1;
public:
B()
{
}
void print()
{
cout<<"Inside B Print()"<<endl;
}
};
int main()
{
B obj;
cout<<sizeof(obj)<<endl;
return 0;
}
Since I have used public access specifier during inheriting class A. Since we know that private member of base class is not accessible at all.
So output of above code should be: 16.
But compiler giving the output as 28.
Can anyone explain this?
The object of class B has inherited the member variables from class A. For example,
class Car {
private:
string color;
};
class BMW : public Car {
private:
string model;
};
Now, any object of BMW will have its own model and color at the same time. But the color member variable won't be accessible unless you write public getters and setter in the Car class.

Cyclic dependency involving global objects C++

So, I'm in this situation right now. I have two classes A and B. The B is subclass of A and there's also a global object of the B class which is initialized in the main. A function of the A class uses that global object and calls its functions. In what order do I have to write the declarations in order for the compiler to read everything?
I keep getting the same errors whatever I try. Namely:
- (x) does not name a type
- invalid use of incomplete type (x)
- forward declaration of (x)
Code example:
class B;
B* B_GLOBAL;
class A{
public:
void A_function(){
B_GLOBAL->B_function();
}
private:
};
class B : public A{
public:
void B_function();
private:
};
int main(void){
B_GLOBAL = new B;
return 0;
}
Move the definition of A_function below the declaration of B:
class B;
B* B_GLOBAL;
class A{
public:
void A_function();
private:
};
class B : public A{
public:
void B_function();
private:
};
void A::A_function(){
B_GLOBAL->B_function();
}
int main(void){
B_GLOBAL = new B;
return 0;
}

How to make a class able to access only certain private members of another class?

Suppose we have two classes:
class Base
{
private:
int x;
public:
void f();
};
class Foo
{
// some variables and methods
};
Now everyone can call Base::f(), but I want only Foo to be able to do so.
In order to achieve this effect, we can make Base::f() private and declare Foo as a friend:
class Base
{
private:
int x;
void f();
friend Foo;
};
The problem with this approach is that Foo has the access to both Base::f() and Base::x (and even to any other private members of Base). But I want Foo to have access only to Base::f().
Is there a way for a class (or a function) to grant an access only to certain private members of another class? Or maybe anyone could suggest a better approach to my problem?
EDIT:
I'll try to specify the access restriction I need. Firstly, Base is an interface in a library (it's an abstract class, in fact). The user uses only the classes derived from Base. Base::f() is called only by Foo which is another class in the library. Hiding Base::f() from the user is important, because only Foo knows when to call it. At the same time, Foo shouldn't mess up the other members of Base.
Very hacky, but this will allow very fine grained access.
class Base
{
private:
int x;
void f();
friend class Base_f_Accessor;
};
class Base_f_Accessor
{
private:
static void f(Base & b) { b.f(); }
friend class Foo;
}
class Foo
{
// some variables and methods
};
You can create another class that contains the data for Base like this:
class BaseData {
protected:
int x;
};
class Base : public BaseData {
friend class Foo;
void f ();
};
Now, Foo can access f as a method of Base like you wanted, but not x. Friendship is not commutative. By using protected, x appears private to everyone except those that derived directly from BaseData.
A better approach might be to use multiple inheritance to define Base, and provide Foo access only to those classes you want from which Base derives.
class With_f {
friend class Foo;
protected:
virtual void f () = 0;
};
class With_g {
protected:
virtual void g () = 0;
};
class Base : public With_f, public With_g {
int x;
void f () {}
void g () {}
};
Here, Foo would have to have a With_f pointer to Base, but it could then access the f method. Foo could not access g.
There's no easy, non-hackish way to achieve that. C++ simply doesn't have such access control granularity. You can play with some inheritance, but increased complexity outweighs any advantages this access restriction might have. Also, this approach doesn't scale - you can grant increased permissions only to one friend class.
Maybe a bit cumbersome, but you could make nested classes where the nesting class is friend, then you can add friends per nested class. This gives some level of granularity:
#include <iostream>
class Nesting
{
friend class Foo;
class Nested1
{
friend class Nesting;
public:
Nested1() : i(3) { }
private:
int i;
} n1;
class Nested2
{
friend class Nesting;
friend class Foo;
public:
Nested2() : j(5) { }
private:
int j;
} n2;
int f() { return n1.i; }
};
class Foo
{
public:
Foo(Nesting& n1) : n(n1) { }
int getJ() { return n.n2.j + n.f(); }
private:
Nesting& n;
};
int main()
{
Nesting n;
Foo foo(n);
std::cout << foo.getJ() << "\n";
}

How to Avoid Duplicate copies of Base Class Members in Derived Class in C++

In my project, there is one Base class and there are 3 different derived classes. I have some macro variables written as const int in the base class. All the derived member is going to access these members and are going to see the same value. Since, its a const, and it is not going to change, maintaining 3 different values will be waste of space. Hence I want a way to maintain just one copy of base class const members so that all the derived class will use the same.
Example
//Base.hpp
Class Base {
const int ZER0;
const int ONE;
};
//Derived1.hpp
class Derived1:public Base {
int some_method1();
};
//Derived1.cpp
int Derived1::some_method1() {
int value = ZERO;
}
//Derived2.hpp
class Derived2:public Base {
int some_method2();
};
//Derived2.cpp
int Derived2::some_method2() {
int value = ONE;
}
//main.cpp
Derived1 d1;
d1->some_method1();
Derived d2;
d2->some_method2();
//Here in both the methods the values are constant, but still the ZERO and ONE are going to have different space. Is there a way, where I maintain only one copy? I could think of static variable. Is it okay to use static inside class and where do I initialize the static variable. Please advice.
PS: This questions might be a duplicate, but I cant find something with similar words, if you feel this is, please feel free to redirect to the corresponding article/question;
If I'm understanding you correctly, would an enum do what you're looking for?
class Base
{
enum
{
ZERO,
ONE
};
};
I think you can possibly use virtual base inheritence to maintain one copy of base ..
//Base.hpp
class Base {
public:
Base() {}
virtual ~Base() {}
protected:
static const int ZER0;
static const int ONE;
};
//Base.cpp
const int Base::ZER0 = 0;
const int Base::ONE = 1;
//Derived1.hpp
class Derived1 : public virtual Base { //using virtual keyword here maintains one copy of base class, thus one copy of ONE and ZERO for all objects since they are static members of Base. You must read about diamond problem of virtual inheritence to understand this properly.
public:
Derived1() :Base() {}
int method1();
};
//Derived1.cpp
int Derived1::method1() {
int value = ZER0;
return value;
}
//Derived2.hpp
class Derived2 : public virtual Base {
public:
Derived2() :Base() {}
int method2();
};
//Derived2.cpp
int Derived2::method2() {
int value = ONE;
return value;
}
//main.cpp
int main() {
Derived1 d1;
d1.method1(); // . instead of -> , -> is used for member access through pointers
Derived2 d2;
d2.method2();
return 0;
}