Cast member of virtual base class - c++

I know that this code won't work and I also know why, but is there an alternative?
class A
{
public:
A(void){}
virtual ~A(void){}
protected:
A* parent;
int a;
};
class B : public virtual A
{
public:
B(void){}
virtual ~B(void){}
protected:
void f(){ ((B*)parent)->a; }
};
It is not possible to cast parent to a B*, since A is a virtual base class. Not casting parent also gives an error. I hope I don't have to make all members public. Does someone have an idea how to access A::a?
Edit
Using friends doesn't work, since classes derived from B don't have access to A::a.

Some options:
Make a public
Create a public setter/getter method for a -
make B a friend of class A (or just the function f())
The 3rd option his works better than the other 2 if you want to allow only A (or a specific function) to have access to members of A. On the other hand with the other 2 options you can make only that member public (but it will be public to everyone)

Making an answer from my comment above because I tested it and it compiles fine.
Without the cast, it probably fails because you are trying to access a protected field of A in B. You can just add a public getter and remove the cast to B*
class A
{
public:
A(void){}
virtual ~A(void){}
int getA() { return a; }
protected:
A* parent;
int a;
};
class B : public virtual A
{
public:
B(void){}
virtual ~B(void){}
protected:
void f(){ (parent)->getA(); }
};

This works:
class A {
public:
A(void){}
virtual ~A(void){}
protected:
A* parent;
int a;
int parent_a(){ return parent->a;}
};
class B : public virtual A
{
public:
B(void){}
virtual ~B(void){}
protected:
void f(){ A::parent_a(); }
};
Note that:
a doesn't get exposed to the outside world,
the retrieved a is necessary the correct one, since B inherit virtually from A, so a successful dynamic cast of parent to B before getting its a field should return the same one as the solution offered above.
Now, why does this work?
Because a class is implicitely friend of itself.

That's what dynamic_cast is for. If you don't want to redesign your code, just replace the C-style cast with a dynamic_cast:
void f() { dynamic_cast<B*>(parent)->a; }
For this to work correctly, A must have at least one virtual function (as this one does). In addition, the cast will produce a null pointer if parent does not, in fact, point to an object of type B.

class B : public virtual A
{
public:
B(void){}
virtual ~B(void){}
protected:
void f(){ this->a; }
};
you're allowed to access protected member from parent class (A mother class of B).

I think the problem here is not so much how to access the element a, but why you need a tree of diamond hierarchies in your design. You should at first step back and evaluate if you really need a tree of diamonds.
If you do, then instead of your current approach, provide A with a nice appropriate (public) abstract interface that can be called from B. When you start accessing parent protected attributes directly you tightly couple components, making it easy to break your code and making it very hard to change your design later in the application's lifespan.

Thanks everyone, some usable possibilities were mentioned, like using friends and creating additional functions for each variable. This could work in some scenarios, but not in my case. Adding each derived class as a friend has the problem that it makes the library less user friendly when they want to add a class. Adding functions per variable would add over hundred extra functions for some classes.
What I did as my final solution was creating a copy instead of a cast. Though it will run a little bit slower, the code will remain clean. To counter the speed problem. Accessing local variables is a lot faster than accessing global variables.
This is how it looks now:
class A
{
public:
A* parent;
virtual ~A(void){}
virtual A & operator = (const A & x)
{
a = x.a;
parent = x.parent;
return *this;
}
protected:
int a;
};
class B : public virtual A
{
public:
B(void){}
virtual ~B(void){}
using A::operator =;
virtual B & operator = (const B & x)
{
A::operator = (x);
return *this;
}
void f(void)
{
B p;
p = *parent;
int x = p.a;//Allowed.
}
};
If you have a better solution, please feel free post it.

Related

Can't access protected member variables of the most base class through std::unique_ptr in diamond

I am not an advanced programmer. Suppose there is a classic diamond inheritance:
class Base
class A: virtual public Base
class B: virtual public Base
class Last: public A, public B
Suppose Base has a variable, m_x, that is common to both A and B, such that only one of A, or B, can be called at a time, not both (which is what is needed). To get around this, this is used:
class Last: public A, public B
{
private:
std::unique_ptr<Base> m_p;
public:
Last(int i)
{
if (i)
m_p = std::unique_ptr<Base>(new A());
else
m_p = std::unique_ptr<Base>(new B());
}
};
This is fine, but now m_p->m_x cannot be accessed anymore because it says it's protected, but both A and B call m_x in their constructors directly, with no problems.
Is this a known limitation or is this the wrong way to do it? If it's wrong, what solutions are there?
Here is some code based on the diagram found here (a bit lower on the page):
#include <iostream>
#include <memory>
class Power
{
protected:
double m_x;
public:
Power() {}
Power(double x): m_x {x} {}
virtual ~Power() = default;
};
class Scanner: virtual public Power
{
public:
Scanner() {}
Scanner(double x): Power(x) {} // scan document
};
class Printer: virtual public Power
{
public:
Printer() {}
Printer(double x): Power(x) {} // print document
};
class Copier: public Scanner, public Printer
{
private:
std::unique_ptr<Power> m_p;
public:
Copier() {}
Copier(double x, int i)
{
if (i)
m_p = std::unique_ptr<Power>(new Scanner(x));
else
m_p = std::unique_ptr<Power>(new Printer(x));
}
void print() { std::cout << this->Power::m_x << '\n'; }
};
int main(int argc, char *argv[])
{
Copier *copier {new Copier(1.618, 0)};
copier->print();
copier = new Copier(3.14, 1);
copier->print();
return 0;
}
Using both this->m_p and this->Power::m_x (according to answers and comments) compiles, but the output is 0.
To be sure I spell it out all: not only I am quite a beginner, but, given the example above, it oesn't really have to stay that way if there is another alternative to call Scanner or Printer only one at a time from inside Copier. I am not asking for opinions, I understand it's forbidden, but I won't reject them coming from more experienced users. After all, I am learning.
Both virtual inheritance and std::unique_ptr are red herrings. The problem comes down to this:
class Base
{
protected:
int m_x;
};
class Last : public Base
{
public:
Last()
{
Base base;
base.m_x = 0; // error
m_x = 1; // no error
}
};
The error is something like error C2248: 'Base::m_x': cannot access protected member declared in class 'Base' or error: 'int Base::m_x' is protected within this context.
The explanation is that protected is a somewhat special case. It does not only work on class level but also on the object level. And you have two relevant objects here:
The Last object which is being created by the constructor, i.e. the one pointed to by this. It's also a Base object because of the is-a inheritance relationship.
The local object named base within the constructor.
Now, the problem is that in the line base.m_x = 0;, you are in the context of the first object and not the second one. In other words, you are trying to access the m_x of base from outside base. C++ simply does not allow this.
A very technical explanation can be found in the C++ standard at §11.4 [class.protected], a more easily understandable one in an excellent answer here on Stack Overflow.
protected doesn't mean quite what you think it does.
Although Last is derived from Base, member functions of Last don't have access to the protected members of any Base object - just those Base objects that are sub-objects of some Last object.
So you can write: this->Base::x because *this is a Last object, but not m_p->x, because *m_p is of static type Base.
As others have noted, I think this is actually an XY problem. Having an object which derives from two classes, and then also has a pointer to another object of one of those classes is very strange indeed. I think you need to clarify what you are trying to do.

Virtual Function During Construction Workaround

I've got a base class that has a virtual function. I want to call that class during the construction because I want the function called for each of the derived classes. I know I can't call a virtual function during construction, but I can't think of an elegant (i.e., avoid repeating code) solution.
What are some work arounds to calling a virtual function during construction?
The reason I want to avoid this is because I don't want to have to create constructors that just call the base class.
class A {
public:
A() {
read();
}
// This never needs to be called
virtual void read() = 0;
}
class B:A {
public:
B():A() { };
read() { /*Do something special for B here.*/ }
}
class C:A {
public:
C():A() { };
read() { /*Do something special for C here.*/ }
}
PS: The Python way of doing this is simply to raise NotImplementedError in A::read(). I'm returning to C++ and I'm more rusty than I thought.
The FAQ perspective.
This is a Frequently Asked Question.
See the C++ FAQ item titled “Okay, but is there a way to simulate that behavior as if dynamic binding worked on the this object within my base class's constructor?”.
It’s very often a good idea to check the FAQ (and generally, googling or altavista’ing) before asking.
The question as “Derived class specific base initialization”.
To be clear, while the literal question above is
“What are some work arounds to calling a virtual function during construction?”
it is evident that what’s meant is
“How can a base class B be designed so that each derived class can specify part of what goes on during B construction?”
A major example is where C style GUI functionality is wrapped by C++ classes. Then a general Widget constructor might need to instantiate an API-level widget which, depending on the most derived class, should be a button widget or a listbox widget or whatever. So the most derived class must somehow influence what goes on up in Widget’s constructor.
In other words, we’re talking about derived class specific base construction.
Marshall Cline called that “Dynamic Binding During Construction”, and it’s problematic in C++ because in C++ the dynamic type of an object during class T construction and destruction, is T. This helps with type safety, in that a virtual member function is not called on a derived class sub-object before that sub-object has been initialized, or its initialization has started. But a major cost is that DBDI (apparently) can’t be done in a way that is both simple and safe.
Where the derived class specific init can be performed.
In the question the derived class specific action is called read. Here I call it derived_action. There are 3 main possibilities for where the derived_action is invoked:
Invoked by instantiation code, called two-phase construction.
This essentially implies the possibility of having a mostly unusuable not fully initialized object at hand, a zombie object. However, with C++11 move semantics that has become more common and accepted (and anyway it can be mitigated to some extent by using factories). A main problem is that during the second phase of construction the ordinary C++ protection against virtual calls on uninitialized sub-objects, due to dynamic type changes during construction, is not present.
Invoked by Derived constructor.
For example, derived_action can be invoked as an argument expression for the Base constructor. A not totally uncommon technique is to use a class template to generate most derived classes that e.g. supply calls of derived_action.
Invoked by Base constructor.
This implies that knowledge of derived_action must be passed up to the constructor, dynamically or statically. A nice way is to use a defaulted constructor argument. This leads to the notion of a parallel class hierarchy, a hierarchy of derived class actions.
This list is in order of increasing sophistication and type safety, and also, to the best of my knowledge, reflects the historical use of the various techniques.
E.g. in Microsoft’s MFC and Borland’s ObjectWindows GUI early 1990’ libraries two-phase construction was common, and that kind of design is now, as of 2014, regarded as very ungood.
This is the factory method approach, putting the factory into the base class:
class A {
public:
virtual void read() = 0;
template<class X> static X* create() {X* r = new X;X->read();return X;}
virtual A* clone() const = 0;
};
class B : public A {
B():A() { };
friend class A;
public:
void read() { /*Do something special for B here.*/ }
B* clone() const {return new B(*this);}
};
class C : public A {
C():A() { };
friend class A;
public:
void read() { /*Do something special for C here.*/ }
C* clone() const {return new C(*this);}
};
Added a clone-method with covariant return type as a bonus.
Using CRTP:
class A {
public:
// This never needs to be called
virtual void read() = 0;
virtual A* clone() const = 0;
};
template<class D, class B> struct CRTP : B {
D* clone() {return new D(*this);}
static D* create() {return new D();}
};
class B : public CRTP<B, A> {
B() { };
public:
void read() { /*Do something special for B here.*/ }
};
class C : public CRTP<C, A> {
C() { };
public:
void read() { /*Do something special for C here.*/ }
};
One way to achieve this, would be simply to delegate it to another class (that is perhaps a friend) and can be sure to be called when fully constructed.
class A
{
friend class C;
private:
C& _c; // this is the actual class!
public:
A(C& c) : _c(c) { };
virtual ~A() { };
virtual void read() = 0;
};
class B : public A
{
public:
B(C& c) : A(c) { };
virtual ~B() { };
virtual void read() {
// actual implementation
};
};
class C
{
private:
std::unique_ptr<A> _a;
public:
C() : _a(new B(*this)) { // looks dangerous? not at this point...
_a->read(); // safe now
};
};
In this example, I just create a B, but how you do that can depend on what you want to achieve and use templates on C if necessary, e.g:
template<typename VIRTUAL>
class C
{
private:
using Ptr = std::unique_ptr<VIRTUAL>;
Ptr _ptr;
public:
C() : _ptr(new VIRTUAL(*this)) {
_ptr->read();
};
}; // eo class C
The workaround is to call the virtual function after construction. You can then couple the two operations (construction + virtual call) in factory function. Here is the basic idea:
class FactoryA
{
public:
A *MakeA() const
{
A *ptr = CreateA();
ptr->read();
return ptr;
}
virtual ~FactoryA() {}
private:
virtual A *CreateA() const = 0;
};
class FactoryB : public FactoryA
{
private:
virtual A *CreateA() const { return new B; }
};
// client code:
void f(FactoryA &factory)
{
A *ptr = factory.MakeA();
}
As mentioned by Benjamin Bannier, you can use CRTP (a template which defines the actual read() function.) One problem with that method is that templates have to always be written inline. That can at times be problematic, especially if you are to write really large functions.
Another way is to pass a function pointer to the constructor. Although, in a way, it is similar to calling the function in your constructor, it forces you to pass a pointer (although in C++ you could always pass nullptr.)
class A
{
public:
A(func_t f)
{
// if(!f) throw ...;
(*f)();
}
};
class B : A
{
public:
B() : A(read) {}
void read() { ... }
};
Obviously, you have the "can't call other virtual functions" problem within the read() function and any function it calls. Plus, variable members of B are NOT yet initialized. That is probably a much worst problem in this case...
For that reason, writing it this way is safer:
B() : A()
{
read();
}
However, in cases like that, that may be the time when you an some for of init() function. That init() function can be implemented in A() (if you make it accessible: i.e. use public A when deriving) and that function can call all the virtual functions as expected:
class A
{
public:
void init()
{
read();
}
};
class B : public A
{
public:
...
};
I know a lot of people say that an init() function is evil because people who create a B object now need to know to call it... but there isn't much else you can do. That being said, you could have a form of factory, and that factory can do the init() call as required.
class B : public A
{
public:
static B *create() { B *b(new B); b->init(); return b; }
private:
B() { ... } // prevent creation without calling create()
};

access protected inherited member with pointer to base class

Can someone explain why this code doesn't work.
class A
{
public:
A(void){}
virtual ~A(void){}
protected:
A* parent;
};
class B : public A
{
public:
B(void){parent = new B;}
~B(void){delete parent;}
protected:
int a;
};
class C : public B
{
public:
C(void){}
virtual ~C(void){}
void f(void){ ((B*)parent)->a; }
};
How is it possible that C isn't able to access members of B?
If I convert parent to a C* in stead of a B* it works fine. But I don't want users to take any unnecessary risks. Is there a cleaner way access a?
Thanks.
From an object of the C class, you can access protected members of B, but only if they're part of some object of class C (maybe yours, maybe not). In other words, to access a from C, you need a pointer (or a reference) to C. This is what the protected modifier means.
The reason for this is the following. The ((B*)parent) pointer may point to some other subclass of B, completely different from C, and that subclass may have the a member inaccessible.

How to expose a member objects interface in C++

C++ : I have a basic object (object A) that contains a member object (object B). The member object interface (object B) needs to be fully exposed through the pointer to object A. What's the best way to do this? I could place the object as a public member but this feels like a hack. I could write wrappers for all B's interface in A but this feels ugly. I could merge the objects but I am doing class serialization to XML so having distinct classes is cleaner. I thought about friend classing but I don't think that applies to this situation.
What is the standard way to resolve this type of issue?
Let B implement an interface IB. A manages an instance of B internally and has a getter getB that returns the IB interface of the private B instance. If you want to protect the B instance, you can make the IB methods const and also hide the destructor (by making it private in IB).
class IB {
private:
~IB();
public:
virtual void method1() = 0;
virtual void method2() = 0;
};
class B : public IB {
public:
virtual void method1() {};
virtual void method2() {};
void destruct() { delete this; }
};
class A {
private:
B myB;
public:
IB *getB() { return &myB; }
};
(This is just to give an idea. It's been 3+ years since I last touched C++. I could have made some blatant errors.)
I reject the notion that doing this at all is a good idea, but I would make it a public member. If you don't like that you can have a getB() method. If possible, I would make it return a const reference instead of a normal reference.
Overload the -> operator in A and in the implementation return the pointer variable of type B.
But as you know you will not be able to access A's members through A's pointer and ->. Also it has the risk of causing confusion who ever read the code.
I meant something like this.
struct A
{
B *p;
B * operator -> ()
{
return p;
}
};

Polymorphism and inheritance of static members in C++

I need to keep a list(vector) of children for every class, and I've got a tricky problem:
class A
{
protected:
int a;
static vector<A*> children;
public:
A(int a): a(a) {;};
virtual void AddToChildren(A* obj);
virtual void ShowChildren();
virtual void Show();
};
class B: public A
{
protected:
int b;
static vector<A*> children;
public:
B(int a, int b): b(b), A(a) { A::AddToChildren(this);};
virtual void Show();
};
class C: public B
{
protected:
int c;
public:
C(int a, int b, int c): c(c), B(a,b) { B::AddToChildren(this);};
virtual void Show();
};
vector<A*> A::children=vector<A*>();
vector<A*> B::children=vector<A*>();
void A::AddToChildren(A *obj)
{
children.push_back(obj);
}
void A::ShowChildren()
{
for(vector<A*>::iterator i=children.begin(); i!=children.end();i++)
(*i)->Show();
}
Adding A(0), B(1,1) and C(2,2,2) and calling a.ShowChildren gives: 1,1 ; 2,2,2 ; 2,2,2
Every time I make an instance of class C the A::children is updated instead of B::children and A::children. Sooo... the class C is added twice to the children of A class, but not added to class B. It helps when I copy the AddChildren class (literally copy) to class B, so that every class has its own AddChildren/ShowChildren. Also I've managed to accomplish this task using pointers, but I'm wondering is there a better way. I think that the problem is somewhere in the "using the right vector", but I don't know how to force the compiler to use the right one.
I would be grateful for any suggestions on whatever I'm doing wrong here.
First of all, thank you all for your comments and help. Using your advice (about my design and virtual GetList()) I managed to simplify my program:
class A
{
protected:
int a;
virtual vector<A*>* GetList();
public:
A(int a): a(a) {;};
A(int a, A* inherited):a(a) { AddToChildren(inherited);};
static vector<A*> children;
virtual void AddToChildren(A* obj);
virtual void ShowChildren();
virtual void Show();
};
class B: public A
{
protected:
int b;
virtual vector<A*>* GetList();
public:
static vector<A*> children;
B(int a, int b): b(b), A(a,this){;};
B(int a, int b, A* inherited) : b(b), A(a,this){AddToChildren(inherited);};
virtual void Show();
};
class C: public B
{
protected:
int c;
public:
C(int a, int b, int c): c(c), B(a,b,this) { };
virtual void Show();
virtual vector<A*>* GetList();
};
vector<A*> A::children=vector<A*>();
vector<A*> B::children=vector<A*>();
void A::AddToChildren(A *obj)
{
GetList()->push_back(obj);
}
void A::ShowChildren()
{
for(vector<A*>::iterator i=GetList()->begin(); i!=GetList()->end();i++)
(*i)->Show();
}
vector<A*> * A::GetList()
{
return & children;
}
vector<A*> * B::GetList()
{
return & children;
}
vector<A*> * C::GetList()
{
return & children;
}
Now its using constructors without calling the upper class, it just calls the proper constructor of the upper class. Its not the best, but i think it's better.
Once more, thank you all for help.
Edit: as ironic points out, this does not apply in the case you posted. I'm leaving it undeleted as it may be useful in other situations.
When you call AddToChildren(), you get A's implementation, which (of course) adds to A's static member.
This is because C++ has no concept of "virtual data". One way round it would be to add a virtual function called GetList(). I A it looks like this (untested code):
virtual vector <a*> * GetList() {
return & A::children;
}
and in B:
virtual vector <a*> * GetList() {
return & B::children;
}
Then change AddToChildren to:
void A::AddToChildren(A *obj)
{
GetList()->push_back(obj);
}
The code of a function only applies to the class it is defined in, even if it is virtual. So, the following function always applied to class A and therefore appends to A::children :
void A::AddToChildren(A *obj)
{
children.push_back(obj);
}
If you want distinct vectors for every class, you have no choice but to repeat code from one class to another (the static variable, its initialization, and either an add-to-children function or a get-children-list function). I would advise against calling virtual functions in constructors, though.
Another approach you might be interested in would be to have a distinct class template for such storage:
template<typename T> struct children
{
static std::vector<T*> list;
static void add(T* t) { list.push_back(t); }
};
B::B() : A() {
children<A>::add(this);
}
C::C() : B() {
children<B>::add(this);
}
Your design intent is not sufficiently clear, which is why the authors of some other answers got confused in their replies.
In your code you seem to make calls to AddToChildren from some constructors but not from the others. For example, you have a children list in A but you never call the AddToChildren from A::A constructor. Also, class C has no its own children list. Why? Is it supposed to share the children list with B?
I can guess that the fact that you are not calling AddToChildren from all constructors means that some constructors are intended to build complete "objects" of given type (these constructors do call AddToChildren), while some other constructors are intended to be used as "intermediate" constructors by descendant classes (these constructors don't call AddToChildren).
Such design might be considered quite questionable and error prone. Note, for example, that C::C calls AddToChildren, which supposedly is adding this to B::children (was it the intent?), and also invokes B::B constructor, which will also add this to B::children. So, the same this value is added to the list twice. This does not seem to make any sense.
You need to figure out what is it you are trying to do and then fix your design. Once you are done with it, you can "virtualize" the list using the technique proposed by Neil (introducing a virtual GetList method). Neil later wrote incorrectly that it will not work. In fact, it will work perfectly fine (again, assuming that I understand your intended design correctly).
(Taking into account the OP's clarifying comments)
So, you want B objects to be added to A::children list and C objects to be added to both A::children and B::children lists. This can be achieved by
class A {
...
int a;
static vector<A*> children;
...
A(int a) : a(a) {}
virtual vector<A*> *GetList() = 0;
void AddToChildren(A* obj) { // note: non-virtual
GetList()->push_back(obj);
}
...
};
class B : public A {
...
int b;
static vector<A*> children;
...
B(int a, int b) : b(b), A(a) {
AddToChildren(this);
}
virtual vector<A*> *GetList() {
return &A::children;
}
...
};
class C : public B {
...
int c;
...
C(int a, int b, int c) : c(c), B(a,b) {
AddToChildren(this);
};
virtual vector<A*> *GetList() {
return &B::children;
}
...
};
Note that despite what was said by other posters, virtual calls do work here and they work exactly as we need them to work to achieve the requested functionality. Note though, that in this case there's no point to make method AddToChildren virtual, the virtuality of GetList alone is sufficient.
Also, the whole thing makes little if AddToChildren just does a push_back. There's no much sense the build such infrastructure for such a "thin" AddToChildren alone. Just do what you want to do explicitly in each constructor.
You haven't show us the implementation of A::AddToChildren or B::AddToChildren, but that's where the problem will be. One or another way, your implementation of B::AddToChildren is adding to the wrong vector. Maybe you didn't specialize the method for B? Can't really tell without seeing that part of the code.
Edit after comments: If you insist on using inheritance here, you could do something like:
class A
{
...
virtual vector<A*> * ChildrenPtr();
};
...
A::ChildrenPtr() {return &A::children;}
B::ChildrenPtr() {return &B::children;}
C::ChildrenPtr() {return NULL;}
void A::AddToChildren(A *obj)
{
vector<A*> * pChildren = ChildrenPtr();
if (pChildren)
pChildren->push_back(obj);
}
In this case, I frankly think that's more confusing, though, not less.
This is very similar to what Neil Butterworth said above, but also has a bit of safety about anyone ever invoking C::AddToChildren(A *obj).
#Neli: Such approach would not solve this concrete problem because in C++ calls to virtual functions from destructors/constructors are actually not virtual. So from the constructor GetList() will still return children of A.
P.s. this should be in comment to the reply, but I could not find appropriate option..
P.P.S. Specially for AndreyT with love
Please read the following carefully. It is from C++ international standard, 12.7.
When a virtual function is called directly or indirectly from a constructor (including from the mem-initializer for a data member) or from a destructor, and the object to which the call applies is the object under construction or destruction, the function called is the one defined in the constructor or destructor’s own class or in one of its bases, but not a function overriding it in a class derived from the constructor or destructor’s class, or overriding it in one of the other base classes of the most derived object (1.8). If the virtual function call uses an explicit class member access (5.2.5) and the object-expression refers to the object under construction or destruction but its type is neither the constructor or destructor’s own class or one of its bases, the result of the call is undefined.