Nested struct attributes inheritance - c++

I read that you can extend a structure by using inheritance. I have a derived class in which I want to have the same struct that its parent but extended with more fields. This seems to work, however when I call a method from the Parent class that modified the structure, it does not have effect in the Child structure attribute. Here, an example of what am I trying:
class Parent
{
public:
struct info
{
int a;
};
info data;
virtual void main(void);
};
void Parent::main()
{
data.a =1;
}
class Child: public Parent
{
public:
struct info2: public info
{
int b;
};
info2 data;
virtual void main(void);
};
void Child::main(void)
{
Parent::main();
data.b = 2;
std::cout << data.a << "\n";
std::cout << data.b << "\n";
}
int main(void)
{
Parent *base;
Child derived;
base = &derived;
base->main();
return 0;
}
This instead of printing 1 and 2 prints 0 and 2. So basically as if the attribute data from the derived class is not modified by the call to Parent::main.
What the right way of doing that? Am I completely doing it wrong?

You mean
void Child::main(void)
{
Parent::main();
data.b = 2;
std::cout << Parent::data.a << "\n";
std::cout << data.b << "\n";
}
The name data declared in the derived class hides the name data declared in the base class. So you need to use a qualified name to access a hidden member of the parent class.
As for data member a of the member data of the derived class then it was not initialized.
Objects of the derived class have two data members data: one is inherited with the type info (which name is hidden in the derived class) and other is the own data member of the derived class.
The base class knows nothing about the data member data of the derived class.
You could define a virtual function within the class info. For example
#include <iostream>
class Parent
{
public:
struct info
{
int a;
virtual void set( int a )
{
this->a = a;
}
};
info data;
virtual void main(void);
};
void Parent::main()
{
data.set( 1 );
}
class Child: public Parent
{
public:
struct info2: public info
{
int b;
void set( int a ) override
{
this->a = a;
}
};
info2 data;
virtual void main(void);
};
void Child::main(void)
{
data.set( 3 );
data.b = 2;
std::cout << data.a << "\n";
std::cout << data.b << "\n";
}
int main(void)
{
Parent *base;
Child derived;
base = &derived;
base->main();
return 0;
}
The program output is
3
2

You're entirely correct, Parent::main() is unable to access Child::data, and knows nothing about any mythical info2 type; to it, Parent::data is all there is, and info is its type.
There are a few easy ways to make Child::main() work with Child::data instead of Parent::data, or to make it access the desired field from each version, but I suspect that's not what you're after. If you want both Parent and Child to see the same data (as an info and an info2, respectively), then data should itself be used polymorphically. For this example, I'll use a regular pointer for simplicity (and in turn, operator. will be replaced with operator->, when accessing data's members), but I would recommend looking into smart pointers such as std::unique_ptr to simplify the memory management.
class Parent
{
public:
struct info
{
int a;
// Chances are, it's going to be deleted through an info* no matter what it is. Therefore, virtual destructor.
virtual ~info() = default;
};
info* data; // Consider using a smart pointer here, like std::unique_ptr.
virtual void main(void);
virtual void output() const; // Just adding this for convenience.
// Default constructor now allows data to be supplied, or creates it if necessary.
Parent(info* dp = nullptr) : data(dp ? dp : new info) {}
// Correct destructor will always be called.
virtual ~Parent() { if(data) { delete data; } }
};
void Parent::main()
{
data->a =1;
}
We now remove the field Child::data, and instead have Child supply its desired data to Parent's constructor.
class Child: public Parent
{
public:
struct info2: public info
{
int b;
};
//info2 data;
virtual void main(void);
void output() const override; // Just adding this for convenience.
Child() : Parent(new info2) {}
};
Child will, when required, view data as an info2 instead of an info.
void Child::main(void)
{
Parent::main();
auto dataPtr = static_cast<info2*>(data); // In Child, we know data is an info2*.
dataPtr->b = 2;
// Just gonna move these to output(), for a cleaner illustration.
//std::cout << "Data->a: " << data->a << "\n";
//std::cout << "Data->b: " << dataPtr->b << "\n";
}
This will then cause data to work as desired, with Parent and Child both having the correct type.
void Parent::output() const {
std::cout << "Parent:\n";
std::cout << "> Data->a: " << data->a << "\n";
}
void Child::output() const /*override*/ {
std::cout << "Child as ";
Parent::output();
auto dataPtr = static_cast<info2*>(data);
std::cout << "Child:\n";
std::cout << "> Data->a: " << dataPtr->a << "\n";
std::cout << "> Data->b: " << dataPtr->b << "\n";
}
This will then perform as expected, as seen live on Coliru. Note that if you want to be able to, e.g., create a Child from a pre-existing Parent, you'll want to add a move constructor that can make an info2 from an info; you should consider following the Rule of Five, or using a smart pointer instead of a raw pointer. ;P

You have to use the below code:
void Child::main(void)
{
Parent::main();
data.b = 2;
std::cout << Parent::data.a << "\n";
std::cout << data.b << "\n";
}

Related

Is it possible to replace a parent class?

If I have a class that's inheriting from another, is it possible to replace the inherited class in the child? I've got a demo of what I'm trying to do below, but I'm not sure the syntax.
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
m_a = a;
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {};
reset(int b)
{
singleNum::this = *singleNum(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
No
You cannot exchange or reset the base class. If it had a reset method of it's own, you could call this, but you cannot call the constructor again.
If you want to do this, you should favor composition over inheritance. You can then create a completely new instance of the inner composition class and replace your existing instance.
Your current demo isn't hard to implement, but you'll need to modify the parent class:
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
reset(a);
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
virtual void reset(int b)
{
m_a = b;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {}
void reset(int b) override
{
singleNum::reset(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
But this is the closest you will get to "replacing the base class". If your case is different than the demo presented and you need to call the base class constructor on an already constructed derived object then no, this is not doable.

Disallow slicing to keep multiple parent class properties in sync

I am deriving an object from two parent classes. These two parents each have different types of properties, but I want the child to keep them in sync with each other. However, I want to disallow users of the library from treating Child like a ParentA or a ParentB accidentally via slicing. For example:
#include <iostream>
class ParentA
{
public:
void modify()
{
std::cout << "modifyA" << std::endl;
}
void readA()
{
std::cout << "readA" << std::endl;
}
};
class ParentB
{
public:
void modify()
{
std::cout << "modifyB" << std::endl;
}
void readB()
{
std::cout << "readB" << std::endl;
}
};
class Child : public ParentA, public ParentB
{
public:
void modify()
{
// Do some bounds checking to make sure ParentA and ParentB stay in sync, then:
ParentA::modify();
ParentB::modify();
std::cout << "modifyChild" << std::endl;
}
};
void Change(ParentA object)
{
object.modify();
}
int main()
{
std::cout << "This is standard:" << std::endl;
ParentA parentA;
parentA.modify();
ParentB parentB;
parentB.modify();
Child child;
child.readA();
child.readB();
child.modify();
std::cout << "Want to avoid this:" << std::endl;
Change(child);
return 0;
}
This call to Change(child); calls ParentA's modify() function, in which the ParentA properties can get out of sync with the ParentB properties, leaving the Child in a bad state.
There are many functions (the read*() ones here) in ParentA and ParentB that I don't want to have to manually forward from Child, so I can't derive privately.
Is there a way to make this call to Change(child) produce a compiler error (without changing the signature of Change)?
There is in fact a way to do this (although said you didn't like it): private or protected inheritance is the C++ mechanism to achieve what you want.
Bear in mind that since your child class is trying to keep some sort of invariant between A and B, if you inherit publicly, someone will find a way to use A or B's interface to violate the invariant anyway so you need to protect against those being used in the child directly, which the restricted inheritance does perfectly.
If there are then some methods in the parent that don't affect the two-class invariant you can using those down into the public section of Child.
As the comments already say the cleanest way might be to just inherit from ParentA and ParentB with private and forward the needed functions.
I had another idea: You could extract the functionality of ParentA and ParentB into 2 abstract classes (AbstractParentA,AbstractParentB) and use these classes as base classes.
This would give you the desired behaviour:
#include <iostream>
class AbstractParentA
{
virtual void no_instance() = 0;
public:
void modify()
{
std::cout << "modifyA" << std::endl;
}
void readA()
{
std::cout << "readA" << std::endl;
}
};
class AbstractParentB
{
virtual void no_instance() = 0;
public:
void modify()
{
std::cout << "modifyB" << std::endl;
}
void readB()
{
std::cout << "readB" << std::endl;
}
};
class ParentA : public AbstractParentA
{
virtual void no_instance() override {}
};
class ParentB : public AbstractParentB
{
virtual void no_instance() override {}
};
class Child : public AbstractParentA, public AbstractParentB
{
virtual void no_instance() override {}
public:
void modify()
{
// Do some bounds checking to make sure ParentA and ParentB stay in sync, then:
AbstractParentA::modify();
AbstractParentB::modify();
std::cout << "modifyChild" << std::endl;
}
};
void Change(ParentA object)
{
object.modify();
}
int main()
{
std::cout << "This is standard:" << std::endl;
ParentA parentA;
parentA.modify();
ParentB parentB;
parentB.modify();
Child child;
child.readA();
child.readB();
child.modify();
std::cout << "Want to avoid this:" << std::endl;
Change(child);
return 0;
}
error C2664: 'void Change(ParentA)': cannot convert argument 1 from 'Child'
note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

Overriding a grandparent's virtual method that was called in grandparent's constructor

I'm having trouble on my c++ code ..
class GrandParent {
public:
GrandParent()
{
printMe();
}
virtual void printMe()
{
std::cout << "GrandParent: printme" << std::endl;
}
}
class Parent : public GrandParent {
public:
Parent(){}
virtual void printMe()
{
std::cout << "Parent: printMe!" << std::endl;
}
}
class Child : public Parent {
public:
Child(){}
void printMe()
{
std::cout << "Child: printMe!" << std::endl;
}
}
int main()
{
Child *p = new Child();
delete p;
}
When I run this code, it prints "GrandParent: printMe".
my goal is to print "Child: printMe!". Is there something wrong in overriding printMe?
What you're trying to do isn't possible. At the time of GrandParent's constructor, the only part of the Child object that has been constructed and initialized is the GrandParent part - including the vtable. That is, when you call printMe(), the entry will be GrandParent's. It's only after Child gets constructed that the vtable entry for printMe() gets updated to point to Child::printMe.
Note that it's good that C++ works like this. If Child::printMe had been the one called, then you'd be calling a member function on a not-yet-constructed object. Nothing good can come of that.
Short answer: That's how C++ works.
When a virtual method is called from the constructor, not the method of the runtime class is used. Instead the method of the compile time class is used.
But there might be an escape using the Curiously Recurring Template Pattern as shown here:
#include <iostream>
template <class T>
class Base
{
protected:
Base()
{
T::printMe();
}
};
class GrandParent : Base<GrandParent>
{
public:
GrandParent()
: Base<GrandParent>()
{}
static void printMe()
{
std::cout << "GrandParent: printMe!" << std::endl;
}
};
class Parent : public GrandParent, public Base<Parent>
{
public:
Parent()
{}
static void printMe()
{
std::cout << "Parent: printMe!" << std::endl;
}
};
class Child : public Parent, public Base<Child>
{
public:
Child()
{}
static void printMe()
{
std::cout << "Child: printMe!" << std::endl;
}
};
int main()
{
GrandParent a;
std::cout << "..." << std::endl;
Parent b;
std::cout << "..." << std::endl;
Child c;
std::cout << "..." << std::endl;
}
Output:
GrandParent: printMe!
...
GrandParent: printMe!
Parent: printMe!
...
GrandParent: printMe!
Parent: printMe!
Child: printMe!
...
But yeah, then you have to deal with static methods and multiple inheritence.

Passing pointer to self

C++ I have a window class, parent, that creates several tab windows, child1, child2, ect..
The parent window has member variables for each child window. I want to access child2 from child1 and thought I might be able to pass a pointer to parent in the constructor of child1 and use parent's pointer to access child2. I don't even really know how to get started. I have tried something like the following and it doesn't compile, starting with the line containing (*this).
class CParent
{
public:
CParent() {};
CChild1 m_Child1(*this);
CChild2 m_Child2;
....
};
class CChild1
{
public:
CChild1(CParent *pParent) {};
int getChild2Number(return pParent->m_Child2.m_number);
};
class CChild2
{
public:
CChild2() {};
m_number = 1;
}
I was wondering if anyone could help out with
1. Getting this to compile without changing up the structure too much
2. Advice on a better way to set this relationship up.
Use the initializer list for the children and pass this. However, be aware that some uses of this are incorrect inside an initializer list (since the object is still under construction and some members will not be initialized yet).
If m_Child1 needs to use m_Child2, you should put m_Child2 above m_Child1 in the class definition so it will be initialized first. Then you can pass the this pointer to m_Child2 like this:
struct CParent {
CParent() : m_Child1( this ) { }
private:
CChild2 m_Child2;
CChild1 m_Child1;
};
You might consider passing just m_Child2 to m_Child1, though, to make the data dependency explicit, to give a hint why m_Child2 must come first, and to not provide a reference to an object under construction. That would look like this:
struct CChild2; // Forward declare the class so CChild1 can accept it
struct CChild1 { // Define CChild1 first because CParent uses it for a member
CChild1( CChild2 &child2 );
// ...
};
// ...
struct CParent {
CParent() : m_Child1( m_Child2 ) { }
private:
CChild2 m_Child2;
CChild1 m_Child1;
};
Your code has several severe issues concerning declaration and definition syntax, member initialization etc. My advise is to keep going with C++ basics.
I suggest to use a dynamic storage for your children since your questions gives a hint that there may be more than two of them.
class CParent;
class CChild
{
public:
CChild (CParent * p_parent);
int get_other_child_number(size_t const other_child);
int number (void) { return m_number; }
private:
CParent * m_parent;
int m_number;
};
class CParent
{
public:
CParent (void) { }
void add_child (void) { m_children.emplace_back(this); }
CChild & child (size_t const child_num) { return m_children.at(child_num); }
CChild const & child (size_t const child_num) const { return m_children.at(child_num); }
size_t num_childs (void) const { return m_children.size(); }
private:
std::vector<CChild> m_children;
};
CChild::CChild (CParent * p_parent) : m_parent(p_parent), m_number(p_parent->num_childs()) { }
int CChild::get_other_child_number(size_t const other_child)
{
return m_parent->child(other_child).number();
}
int main()
{
CParent par;
par.add_child();
par.add_child();
cout << "Number of Child 0 is " << par.child(0).number() << endl;
cout << "Number of Child 1 is " << par.child(1).number() << endl;
cout << "Number of Child 0 from Child 1 is " << par.child(1).get_other_child_number(0) << endl;
cout << "Number of Child 1 from Child 0 is " << par.child(0).get_other_child_number(1) << endl;
}

Polymorphic copy-constructor with type conversion

I need to copy-construct an object simultaneously changing it's type to another class being a member of the same class-hierarchy. I've read about polymorphic copy-constructors and (hopefully) understand the idea behind it. Yet, I still don't know if this pattern applies to my case and, if so, how to implement it. I think it's best if I show what I need on an example.
There is a Base class and two child classes, Child1 and Child2. I need to create an object of type Child2 basing on Child1, ie. most of all, I need to copy the object p_int is pointing to from Child1 to Child2. I've written a simple program to illustrate it:
#include <iostream>
using namespace std;
class Base {
public:
Base() { p_int = new int; *p_int = 0; }
~Base() { delete p_int; }
virtual Base* clone() const = 0;
void setpInt(int val) { *p_int = val; }
void setInt(int val) { a = val; }
virtual void print() {
cout << "Base: ";
cout << (long)p_int << ":" << *p_int << " " << a << endl;
}
protected:
int* p_int;
int a;
};
class Child1 : public Base {
public:
Child1() {};
Child1(const Child1& child) {
p_int = new int (*child.p_int);
a = child.a + 1;
}
Base* clone() const { return new Child1(*this); }
void print() {
cout << "Child1: ";
cout << (long)p_int << ":" << *p_int << " " << a << endl;
}
};
class Child2 : public Base {
public:
Child2() {};
Child2(const Child2& child) {
p_int = new int (*child.p_int);
a = child.a + 1;
}
Base* clone() const { return new Child2(*this); }
void print() {
cout << "Child2: ";
cout << (long)p_int << ":" << *p_int << " " << a << endl;
}
};
int main() {
Child1* c1 = new Child1();
Child2* c2;
c1->setpInt(4);
c1->print();
c2 = (Child2*)c1->clone();
c2->print();
}
Unfortunately, the outcome is as below, ie. there is no type conversion:
Child1: 162611224:4 0
Child1: 162611272:4 1
What exactly do I need to implement, to be able to achieve what I need? I'm starting to think there is a type-conversion mechanism I need to implement rather than a polymorphic copy-constructor, but I'm confused already.
EDIT: Asked a follow up here
Simplest solution would probably be to implement a Child2 constructor taking a Child1& as parameter. Then you could simply call:
Child2* c2 = new Child2(*c1);
If you only have 2 child classes, then the easiest way is to create a conversion constructor:
class Child2: public Base
{
public:
Child2(Child1 const& child)
{
p_int = new int (*child.p_int);
a = child.a + 1;
}
};
c2 = new Child2(*c1);
If you have several Child classes, and you need to create a Child2 from any of them, then you could do something like this:
class Base
{
public:
void CopyFrom(Base* base)
{
p_int = new int (*base.p_int);
a = base.a + 1;
}
};
class ChildX: public Base
{
public:
static ChildX* CreateFrom(Base* base)
{
ChildX ch = new ChildX();
ch->CopyFrom(base);
return ch;
}
};
c2 = Child2::CreateFrom(c1);
c2 = (Child2*)c1->clone();
Here is a serious bug, and the c-style cast hides the bug.
If you use C++-style cast, then it will not hide the bug, and you will know it. In this case, the C++-style cast is : dynamic_cast. Use it to discover the bug yourself.
As it is clear from the code thatc1-clone() creates a clone of c1 whose type is Child1* and clone() returns a pointer of type Base* (after upcasting from Child1*), which you're trying to down-cast to Child2*. The cast should fail if you use proper cast : dynamic_cast.
The clone() patterns allows you to create a valid copy/clone of the object of a child class having just the base reference, e.g. in your case it allows you to do the following:
Base* basePtr = getBaseOrSomeDerivedObject();
Base* copy = basePtr.clone(); // Create a copy that is an object of an actual basePtr's type.
What you could need is a "copy-constructor" that allows you to copy from a base class, e.g.:
class Base {
public:
// [...]
Base(const Base& other) : a(other.a + 1)
{
p_int = new int(*(other.p_int));
}
// [...]
};
class Child2 : public Base {
public:
// [...]
Child2(const Base& base) : Base(base) {}
// [...]
};
int main() {
// [...]
c2 = new Child2(*c1);
c2->print();
}
Result:
Child1: 7275360:4 0
Child2: 7340936:4 1