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.
Related
I'd like to have two non-inheritance-related and non-friends classes, class A and class B. However, i also want that class B can only be instantiated by class A, assuming that class B has a private constructor.
Is there any workaround this without having to use templates?
Rather than having a private constructor you could make your class B "private" by not placing it in any header files.
You can achieve this by using an interface class.
The client programmer can not instantiate the interface class because it is pure-virtual and it can not instantiate the implementation because it has not been declared.
The only way to instantiate it is through a factory function like this:
The public interface:
// classes.h
// pure virtual interface
struct B
{
virtual ~B() {}
virtual void func_1() = 0;
virtual void func_2() = 0;
};
class A
{
public:
// factory method
B* create_B();
};
The "private" implementation:
// classes.cpp
#include "classes.h"
// the *actual* class B
class B_Implementation
: public B
{
public:
void func_1() override
{
// do stuff
}
void func_2() override
{
// do stuff
}
};
B* A::create_B()
{
return new B_Implementation;
}
The usage:
int main()
{
A a;
auto b = std::unique_ptr<B>(a.create_B());
}
If this method is not appropriate to your situation then friend is your only friend.
In c++, Is there a standard way to create a function in a base class that can use the variables of derived classes?
class Foo{
private:
int x;
public:
Foo(){
x = 2;
}
void print(){
std::cout << x << std::endl;
}
};
class Derived : public Foo{
private:
int x;
public:
Derived(){
x = 4;
}
};
void main()
{
Derived a;
a.print();
}
This code prints the variable of the base class ( 2 ). Is there a way to make a function used by many derived classes to use the class's private variables without passing them as parameters?
Edit: My intentions are, to avoid writing the same code for each derived class.
For example, I want a get_var() in all, but this function should return the variable of that own class. I know I can make virtual and override, but I was looking for a way that I don't need to write again and again.
No, it is not possible for the base class to access anything in the derived class directly. The only way for a derived class to share anything with its base class is by overriding virtual member functions of the base class.
In your case, however, this is not necessary: the derived class can set variable x in the base class once you make it protected, and drop its own declaration as unnecessary:
class Foo{
protected: // Make x visible to derived classes
int x;
public:
Foo(){
x = 2;
}
void print(){
std::cout << x << std::endl;
}
};
class Derived : public Foo{
public:
Derived(){
x = 4;
}
};
Consider the following example:
class A{
public: virtual void hello() = 0;
};
class B: public A{};
class C {
public: void hello(){
cout<<"Hi";
}
};
class D: public B, public C{};
The idea is that I would like to inject the implementation of hello into D through C. This doesn't seem to work unless I make C inherit from A too. Since that leads to diamond inheritance, I end up using virtual inheritance.
Is there any alternative to forcing an implementation into a derived class, without disturbing the abstract classes A and B here?
EDIT: I want a solution where I don't need to explicitly write code within D. This is because, I have many classes like D having the same implementation, which is exactly why I would like to push that implementation up to some class from which all of them inherit.
You can rewrite C as a template class that inherits from it's template argument and then derive D from C.
template <class Base>
class C : public Base {
public: void hello(){
cout<<"Hi";
}
};
class D: public C<B> {};
You can consider static inheritance/ policy classes when you need to inject an outside method into a class hierarchy. Note that injecting the method usually means that the method does not have the same name as an existing virtual in the class hierarchy (if it does, you are forced to use virtual inheritance or explicitly call with the scope :: or insert it in the class hierarchy). I called the method externalHello here.
The other options work fine as well but they conceptually point more to the fact that the injected method is not really an abstract method that could be used outside of this class hierarchy but should have been part of it in the first place.
class A
{
public:
virtual void hello() = 0;
};
class B: public A
{
public:
void hello()
{
cout<<"Hi from B" << endl;
};
};
template<typename T> class C1
{
public:
void injectedMethodUnrelatedToClassHierarchy()
{
cout<<"Hi from C1 with unrelated method" << endl;
};
void externalHello()
{
static_cast<T*>(this)->hello(); // will still call hello in B
injectedMethodUnrelatedToClassHierarchy(); // this will call hello here
};
};
class D: public B, public C1<D>{};
With client code:
D dx;
dx.hello();
dx.externalHello();
dx.injectedMethodUnrelatedToClassHierarchy();
It may work
#include<iostream>
using namespace std;
class A
{
public:
virtual void hello() = 0;
};
class C {
public: void hello(){
cout<<"Hi\n";
}
};
template<typename T>
class B: public A, public T
{
public:
void hello() override{ //override A::hello()
//do other staff
T::hello(); // call C::hello()
}
};
class D: public B<C>{
};
int main()
{
D d;
d.hello();
return 0;
}
Derived class function cannot access even the public members of the base class when the access specifier is private. But how is it that the function 'xyz' of my derived class able to call 'showofb'?
I even tried it by calling the function 'showofb' in the constructor of C. In both cases it works.
How is it able to call the function 'showofb' ?
class B
{
public:
B()
{
cout<<":B:"<<endl;
}
void showofb()
{
cout<<"show of b"<<endl;
}
};
class C : private B
{
public:
C()
{
cout<<":C:"<<endl;
}
void xyz()
{
showofb();
}
};
int main()
{
C c1;
c1.xyz();
}
Private inheritance inherits the public members of the parent as the private members of the child. A class can call its own or inherited private members.
Consider this:
class B
{
public:
B()
{
cout<<":B:"<<endl;
}
void showofb()
{
cout<<"show of b"<<endl;
}
};
class C : private B
{
public:
C() {}
};
class D : public B
{
public:
D(){};
}
int main()
{
C c1;
c1.showofb(); // WONT WORK
D d1;
d1.showofb(); // WILL WORK
}
B::showofb() is a public function. So it can be called by C. If you modify B to make showofb private, C will no longer be able to call it.
The private inheritance means that all public and protected members of B are inherited as private by C. So C can still call public and protected members of B, but any classes derived from C will not be able to call members of B.
user1001204, you appear to have a mistaken concept of private inheritance. That class C inherits from class B via private inheritance means that the inheritance relationship is hidden to anything that uses class C. Private inheritance does not hide the inheritance relationship inside Class C itself.
I am trying to figure out an interesting multiple inheritance issue.
The grandparent is an interface class with multiple methods:
class A
{
public:
virtual int foo() = 0;
virtual int bar() = 0;
};
Then there are abstract classes that are partially completing this interface.
class B : public A
{
public:
int foo() { return 0;}
};
class C : public A
{
public:
int bar() { return 1;}
};
The class I want to use inherits from both of the parents and specifies what method should come from where via using directives:
class D : public B, public C
{
public:
using B::foo;
using C::bar;
};
When I try to instantiate a D I get errors for trying to instantiate an abstract class.
int main()
{
D d; //<-- Error cannot instantiate abstract class.
int test = d.foo();
int test2 = d.bar();
return 0;
}
Can someone help me understand the problem and how to best make use of partial implementations?
You don't have diamond inheritance. The B and C base classes of D each have their own A base class subobject because they do not inherit virtually from A.
So, in D, there are really four pure virtual member functions that need to be implemented: the A::foo and A::bar from B and the A::foo and A::bar from C.
You probably want to use virtual inheritance. The class declarations and base class lists would look like so:
class A
class B : public virtual A
class C : public virtual A
class D : public B, public C
If you don't want to use virtual inheritance then you need to override the other two pure virtual functions in D:
class D : public B, public C
{
public:
using B::foo;
using C::bar;
int B::bar() { return 0; }
int C::foo() { return 0; }
};
You need to make your base classes virtual in order for them to inherit properly. The general rule is that all non-private member functions and base classes should be virtual UNLESS you know what you're doing and want to disable normal inheritance for that member/base.