Access private members of class that is friends with parent class - c++

Consider the following
class Base;
class A {
int x;
friend class Base;
};
class Base {
protected:
A a_obj;
public:
Base(){
a_obj.x; // works
}
};
class Derived : public Base {
public:
Derived(){
a_obj.x; // not accessible
}
};
I could make public getters and setters for x, or make the object public, but that is not preferrable. Assuming there is a bunch of derived classes, adding friend class Derived in class A would make the code too verbose. Is there a way to say "A is friends with class Base and all it's children"

Is there a way to say "A is friends with class Base and all it's children"
No.
What you can do is make the base a friend (as you did), and write a protected accessor in the base that the children can use to access the private member.

In short, c++ rule is that friendship is not inheritable.
To achieve what you need, you can add static protected method as accessor in a Base class.
But, if you really need to make it w/o accessors or getters
you can make it with reinterpret_cast, but it would be hack and its not recommended.

Is there a way to say "A is friends with class Base and all it's children"
No
You need to fix your design. Classes should not be granted access to members of all types derived from a base class. As per your code, I think you need to modify the private member of a class in the constructor of other class.
One possible solution is using parameterized constructor. You can call constructor of class A from classes Base and Derived.
class Base;
class A {
int x;
public:
A(int in): x(in)
{
}
};
class Base {
protected:
A a_obj;
public:
Base(int in): A(in)
{
}
};
class Derived : public Base {
public:
Derived(): Base(5)
{
}
};

Related

How do I inherit only the member functions in C++?

Say I have a base class Base, and a derived class Derived.
class Base
{
public:
void f1(void);
...
int data1;
...
};
class Derived : Base
{
... add stuff here that's unique to Derived
};
How can Derived inherit only the functions (i.e., f1()) and NOT the data (i.e., data1) from Base?
having attribute of a base class that is not needed in derived class is a hint for bad inheritance
in your case i assume you are going to have another derived class that needs those data members, otherwise it wouldnt make sense
then why not do something like this:
class Base
{
public:
void f1(void);
...
};
class DerivedClass : Base
{
... add stuff here that's unique to Derived
};
class DerivedClass2 : Base
{
public:
int data1;
....
}
if you have more derived classes that needs those data member i suggest you to make separate base class, one for functions and one for data members.

Superclass Setting Object of Subclass Data

I have a base class in C++ that has some protected member variables (although, I do not think it is relevant that it is protected vs. private in this case).
I have a derived class that derives from this base class. In it, there is a public function that creates an object of the base class and returns that object. However, in that function I need to be able to set the protected member variables into a special state.
Example:
class Base
{
protected:
int b_value;
};
class Derived : public Base
{
public:
Base createBase()
{
Base b;
b.b_value = 10;
return b;
}
};
I specifically only want the derived class to be able to the protected member variable. I do not want a public accessor method in the base class.
I originally tried to fix this by making the derived class's createBase() function be a friend of the Base class. Like so:
class Base
{
protected:
int b_value;
friend Base Derived::createBase();
};
class Derived : public Base
{
public:
Base createBase()
{
Base b;
b.b_value = 10;
return b;
}
};
As you can see, this will not compile since Derived has not been defined yet. If it matters, these two classes are defined in separate header files. I guess one way to describe this problem is a "chicken and egg" problem where one needs the other first.
I have a feeling this has to be a "I am not designing my classes correctly and need to rethink how I am doing this" but I cannot figure out how to get this to work.
You can forward declare Derived and then make it a friend in Base :
class Derived;
class Base
{
friend class Derived;
protected:
int b_value;
};
class Derived : public Base
{
public:
Base createBase()
{
Base b;
b.b_value = 10;
return b;
}
};
However this design seems seriously flawed to me as you already stated, you should probably make createBase() a static public method in your Base class and have a setter for b_value or a constructor that sets it.
Remember that right now inside createBase(), this->b_value is also available.

getter inheritance issue with 2 classes

I've 2 classes (voluntary as simple as possible) and I'm working with Qt on Mac OS X:
//Class A
class A
{
protected:
int getX(){return _x;};
private:
int _x;
};
//Class B
class B : A
{
void method(){qDebug() << this->getX();}
};
And the compiler throws:
error: 'getX' is a private member of 'A'
Am I missing something?
I've tried with:
qDebug() << this->A::getX();
Which doesn't work either!
When you don't specify the type of inheritance the default is taken as private.
In private inheritance,
Base Class' public members are private.
From standard docs, 11.2.2
In the absence of an access-specifier for a base class, public is
assumed when the derived class is defined with the class-key struct
and private is assumed when the class is defined with the class-key
class.
there are three types of inheritance:
public
protected
private
the dafult mode for class is private, and for struct it is public:
In the absence of an access-specifier for a base class, public is
assumed when the derived class is defined with the class-key struct
and private is assumed when the class is defined with the class-key
class.
[From C++ standard, 11.2.2]
So, when you say:
class B: A
this is private inheritance and thus all public and protected members of a base class will be inherited as private. What you need is
class B: public A
or
class B: protected A
Private and protected inheritance is used more often where defining implementation details. Private bases are most useful when defining a class by restricting the interface to a base so that stronger guarantees can be provided. For example, Vec adds
range checking to its private base vector (§3.7.1) and the list of pointers template adds type checking to its list<void*> base -> see Stroustrup ("C++..." §13.5).
Example:
//Class A
class A
{
public:
int getX(){return _x;};
protected:
int getX2(){return _x;}
private:
int _x;
};
//Class B
class B : protected A //A::getX and A::getX2 are not visible in B interface,
^^^^^^^^^ // but still we can use it inside B class: inherited
// members are always there, the inheritance mode
// affects only how they are accessible outside the class
// in particular for a children
{
public:
int method(){ return this->getX();}
int method2(){ return this->getX2();}
};
int main(int argc, char** argv) {
B b=B();
printf("b.getX(): %d",b.method()); // OK
printf("b.getX(): %d",b.method2()); // OK
return 0;
}
Further effects to inheritance
Additionally, when you declare class as
class B: A
being the same as class B: private A further inheritance becomes unavailable: only class that derives from A and its friends can use A public and protected members. Only friends and members of B can convert B* to A*.
If A is a protected base then its public and protected members can be used by class B and its friends and by classes derived from B and their friends. Only friends and members of B and friends and members of class derived from B can convert B* to A*.
If A is a public base finally, then its public members can be used by any class and its protected members can be used by derived classes and their friends and by classes derived from B and their friends. Any function can convert B* to A*.
Note also that you cannot cast constness with dynamic_cast or static_cast, it is said that they both respect constness. They both respect access controls also (it is not possible to cast to a private base [because only derived class methods might do Derived* -> Base* and methods of classes being friends to this {friend declaration is in Base}])
more in Stroustrup ("C++", 15.3.2)
When you inherit a class from another, the mode of inheritance should be mentioned. So, you have to declare as
class B: public A
Then you won't have the error
Try this:
//Class A
class A
{
protected:
int getX(){return _x};
private:
int _x;
};
//Class B
class B : public A
{
void method(){qDebug() << this->getX();}
};
You forgot the keyword public, you don't use this as a pointer and you forgot the ; at the end of the classes.
Your code should be as follows:
class A {
protected:
int getX() { return _x; }
private:
int _x;
};
//Class B
class B : public A {
void method() { this->getX(); }
};
They were many errors:
class B: public A;
this->getX();
commas after class declarations
You forgot ; in your getter return
int getX() { return _x; };

why does the derived class inherit the private members of the base class? [duplicate]

This question already has answers here:
Do Sub-Classes Really Inherit Private Member Variables?
(7 answers)
Closed 5 years ago.
I know that the derived class can't access the private members of the base class, so why does the derived class inherit the private members of the base class? Is there any case that it is useful?
Thanks!
The derived class needs the private members even though it can't access them directly. Otherwise it's behavior would not build on the class it is deriving from.
For example, pretend the private stuff is:
int i;
and the class has a geti() and seti(). The value of i has to be put somewhere, even if it is private,
The public and protected methods of the base class can still access private variables of the base class, and these methods are available in the derived class.
The base class can still use the private member variables & methods.
If you want the derived classes to have access to members but keep those members hidden from the outside world, make them protected:.
Here's an example to illustrate:
class Base
{
public:
Base() : val(42.0f) {};
float GetValue() const
{
return val_;
}
private:
float val_;
};
class Derived : public Base
{
public:
float ComputedValue() const
{
return GetValue() * 2.0f;
}
};
Don't forget that the base class may have methods that are not private, and thus accessible by the derived class. Those protected or public base class methods can still invoke the private base class methods. This is particularly useful if you want to lock down core functionality in the base class, such as with a Template Method design pattern implementation:
class base
{
public:
virtual ~base() { /* ... */ }
virtual void base_func() { foo_private (); }
virtual void do_func() = 0;
private:
void foo_private()
{
// pre-do_func() operations
do_func();
// post-do_function operations
}
};
class derived : public base
{
public:
void derived_func() { base_func(); }
virtual void do_func()
{
// Derived class specific operations
}
};
The reason is because derived classes have an is-a relationship to the superclass.
A derived class instantiation IS A superclass instantiation...just with more (or less due to setting some superclass functions private) stuff.
As has been outlined by other answers here, the derived class syntactically cannot access the private members of the base class; but it needs to have a copy of the same in its memory layout. Think of casting. using 'C' casting you can cast a derived to a private base. The compiler would then need the correct memory offset in order to produce a valid memory-layout for the base object.
Ex.
class Base {
public:
void printA() {
a = 10;
std::cout << a << std::endl;
}
private:
int a;
};
class Derived : private Base{
int b;
};
Derived* d = new Derived;
Base* b = (Base*)d;
b->printA();
The derived class doesn't "inherit" the private members of the base class in any way - it can't access them, so it doesn't "inherit" them.
An instance of the derived class contains instances of the private members of the base class, for obvious reasons.
So I don't even know what you mean by that question.
when derived class object is created, base class constructor is also called for base object creation. if private members of base class are not allocated memory , the base object will be incomplete.
hence derived class object inherits private members of base, as they are created during creation of base class object, but are not accessible as they are private.
Although the private members are not accessible from the base class, they are inherited by them because these properties are used by the derived class with the help of non-private functions.
Private members of the base class are not directly accessed, but derived by base class by derived class.

How to access a data class's private member variable from another derived class whose parent class is a friend class of the data class?

I have three classes:
A data holder class CDataHolder, which uses a Pimpl pattern
class CDataHolder
{
public:
// ...
private:
friend class CBase;
struct PImpl;
PImpl* iPimpl;
};
A base class CBase, which need to access the iPImpl member in CDataHolder, so it is a friend class of CDataHolder
class CBase:
{
protected:
CDataHolder::Pimpl* getDataHolderPimpl();
};
A derived class CDerived from CBase, which need to access the same iPimpl member also. Here occurs a problem.
The derived class cannot use the iPimpl member although its parent class is a friend class. like this:
class CDerived : public CBase
{
public:
void doSth() {
CDataHolder::Pimpl *pImpl = getDataHolderPimpl(); // this line raises an error:
// "illegal access from CDataHolder to protected/private member CDataHolder::PImpl"
}
};
There are plenty of derived classes, so it's not a good way for each derived class to put a "friend class CDerivedXXX" line in CDataHolder class.
How to overcome this issue? Is there a better way to do this? Thanks in advance.
Since you have declared struct PImpl in the private part of CDataHolder class, only friends of CDataHolder can access the same. Why don't you put a forward declaration struct PImpl in the public section or even better before the CDataHolder class?
Friend is (rightfully) very limited and can't be inherited. I hate to beg the question, but maybe either A) you need public access to PImpl or some aspect of it, or B) you need the DataHolder class to do something with PImpl for you.