I'm trying to understand inheritance in C++.
I want to dynamically create an array in a derived class and pass the array pointer to the base class, and then the base class fills in the array. Finally I want to print the array from the derived class.
I wrote the following code but when I run this, the program crashes and I get a segmentation fault error.
How should I implement this?!
class Base {
private:
int* array;
public:
Base(int* a) {
array = a;
for(int i = 0 ; i < 10 ; i++) {
array[i] = i;
}
}
};
class Child : public Base {
private:
int* array;
public:
Child() : array(new int[10]), Base(array) {}
void print() {
for(int i = 0 ; i < 10 ; i++) {
cout << array[i] << endl;
}
}
};
The problem here is that the order of items in the initializer list does not influence the order in which the initialization is actually performed; only the order in which the members are declared is considered. Moreover, the initialization of the base always happens first.
Therefore, the Child constructor is actually executed as follows:
Base(array) is invoked (array is not set here!)
array is assigned a valid value.
Fortunately, all you need to do to fix this problem is to remove the array from the Child: it is redundant anyway:
class Child : public Base {
public:
Child() : Base(new int[10]) {
}
void print() {
for(int i = 0 ; i < 10 ; i++) {
// Make a[] protected in the parent
cout << a[i] << endl;
}
}
};
class Base
{
protected:
int *array;
...
}
If you would rather not make a protected in the parent, you can fix your code as follows (demo):
Child() : Base(array = new int[10]) {}
This is suboptimal, though, because a redundant member is kept in all instances of Child.
Base subobjects are initialised before class members, even if you write the initialisers in another order. So here:
Child(): array(new int[10]), Base(array)
the Base object is initialised first, using the uninitialised value of array.
Solutions include:
make Base::array accessible from Child, so it doesn't need its own copy;
move print into the base class, so that Child doesn't need to access array;
do something nasty like Child() : Base(array = new int[10]), if you really need a redundant copy of an inaccessible variable for some reason.
Make sure you've enabled compiler warnings; they should have caught this error.
It's because the base object is constructed first, and only then the child is constructed.
This means that your array is unintialised.
Put some tracing message at the begin and end of each of your consutructors, and you'll get a better understanding of how things work.
One solution would be to use std::array instead of raw pointer like the example below:
#include <iostream>
#include <array>
template<typename T, std::size_t N>
class Base
{
private:
std::array<T, N> const &array;
public:
Base(std::array<T, N> const &a) : array(a) { }
void print() const {
std::cout << "Printing array from Base class!" << std::endl;
for(auto i : array) std::cout << i << " ";
std::cout << std::endl;
}
};
template<typename T, std::size_t N>
class Child : public Base<T, N> {
private :
std::array<T, N> array;
public:
Child() : Base<T, N>(array) {
for(auto &i : array) i = 10;
}
void print() {
std::cout << "Printing array from Child class!" << std::endl;
for(auto i : array) std::cout << i << " ";
std::cout << std::endl;
}
};
auto main() -> int {
Child<int, 10> c;
c.print();
Base<int, 10> *b = &c;
b->print();
return 0;
}
Live Demo
Thus:
You wouldn't have to worry about releasing previously allocated memory.
Your Base class keeps a constant reference to the array object of the Child class. Thus, you save memory.
Related
I was translating a Java program of mine to C++. I got to a problem trying to use polymorphism the same way as in Java.
My code looks something like this:
class Base
{
public:
virtual void print() = 0;
};
class Derived_1 : public Base
{
public:
void print()
{
std::cout << "1" << std::endl;
}
};
class Derived_2 : public Base
{
public:
void print()
{
std::cout << "2" << std::endl;
}
};
The next are two versions of my main method that I have tried, both give me compiler errors:
1:
int main(int argc, char const *argv[])
{
std::vector<Base> v;
v.push_back(Derived_1());
v.push_back(Derived_2());
for(Base i: v)
{
i.print();
}
return 0;
}
Error:
object of abstract class type "Base" is not allowed:C/C++(322)
main.cpp(35, 14): function "Base::print" is a pure virtual function
2:
int main(int argc, char const *argv[])
{
std::vector<Base*> v;
v.push_back(new Derived_1());
v.push_back(new Derived_2());
for(Base* i: v)
{
i.print();
}
return 0;
}
Error:
expression must have class type but it has type "Base *"C/C++(153)
How would you guys solve this?
Coming from java to c++, there are a lot to take-care; Especially memory management!
In your first shown case, you are slicing the objects. See What is object slicing?
In order to access the virtual functions, you should have used std::vector<Base*> (i.e. vector of pointer to Base), or std::vector<std::unique_ptr<Base>> or std::vector<std::shared_ptr<Base>>(i.e. vector of smart pointer to Base).
In your second shown code, your v is a vector of pointer to Base, meaning you need to access the members via the -> operator.
i.e. You should have accessed the print() as follows:
i->print();
^^^
Or alternatively:
(*i).print();
^^^^^
Also note that:
In your second case, whatever you newed must be deleted, so that the program doesn't leak memory. Alternately, we have smart memory management
The Base is missing a virtual destructor, which will lead to undefined behavior when deleteing the ovjects. You should add one for defined behavior. See: When to use virtual destructors?
Using std::unique_ptr, your code will look like (example code):
#include <memory> // std::unique_ptr, std::make_unique
class Base
{
public:
virtual void print() /* const */ = 0;
// add a virtual destructor to the Base
virtual ~Base() = default;
};
class Derived_1 : public Base
{
public:
void print() override /* const */ {
std::cout << "1" << std::endl;
}
};
class Derived_2 : public Base
{
public:
void print() override /* const */ {
std::cout << "2" << std::endl;
}
};
int main()
{
std::vector<std::unique_ptr<Base>> v;
v.reserve(2); // for unwanted re-allocations of memory
v.emplace_back(std::make_unique<Derived_1>());
v.emplace_back(std::make_unique<Derived_2>());
for (const auto& i : v) // auto == std::unique_ptr<Base>
{
i->print();
}
return 0;
}
I wonder if someone could explain the solution to this...
Top class has a vector of Base class.
Each derived class of Base class has a different data struct.
Base class has a vector of the derived class data struct.
Top class needs to access the size of the struct footprint and well as the size of the struct vector and the underlying array.
Top class is blind to the derivatives of the base class.
If I template then Top class needs to be template aware and this will not work.
When I derive, top class only see base class.
I am not able to make the struct virtual ( this would have been the ideal solution. )
The derived class needs to define, or layout, the struct.
Top class needs access to underlying array.
How can I solve this?
#include <iostream>
#include <string>
#include <vector>
class Base {
public:
struct Data {
};
Data data;
std::vector<Data> myData;
};
class Foo1 : public Base {
public:
struct Data {
std::string s1;
std::string s2;
std::string s3;
};
};
class Foo2 : public Base {
public:
struct Data {
int i1;
double d2;
std::string s3;
};
};
class Top {
public:
std::vector<Base> foos;
void test() {
for (std::vector<Base>::iterator f = foos.begin(); f != foos.end(); f++) {
std::cout << "Data Size = " << sizeof((*f).data) << std::endl;
}
}
};
int main(int argc, char* argv[])
{
std::cout << "Test Begin" << std::endl;
Foo1 f1;
Foo2 f2;
Top t;
t.foos.push_back((Base)f1);
t.foos.push_back((Base)f2);
t.test();
std::cout << "Test End" << std::endl;
}
class Base {
public:
struct Data {
};
Data data;
std::vector<Data> myData;
};
This declares a class, Base, with an inner class Data which is, basically, empty, and a Data class member called data, basically an object that contains nothing.
Deriving from Base makes no difference, whatsoever, with any of this. This is what this class is, and defining some other inner class in a derived clas, that happens to have the same name, Data, doesn't change the fact that Base has a member called data that's this Data that you see right there. Derived classes in C++ don't work this way. All they do is define "things" in addition to what they inherit from the base class. The only thing they override and reimplement, in a general sense, would be any virtual methods.
std::vector<Base> foos;
In addition to all of that, this is a vector of Base objects. Putting some derived class in here will result in object slicing, leaving with only Base classes, in the vector.
Object slicing is adequately explained in many other questions here, so I'll refer you to them for more information. But in your case you'll also need to rethink your overall class design:
class Foo1 : public Base {
public:
struct Data {
All this does is define a new class, Foo1::Data. Base::Data is still what it always was, an empty class, and data in the Base is still a Base::Data, nothing's changed about it.
How can I solve this?
It's really not possible to give an accurate answer to this without a complete understanding of how all these classes are intended to be used. Here are just several possibilities:
Just declare a Data in each derived class, and put data in the derived class
Use virtual methods for everything, with Data being just an internal, private, implementation detail of each derived class
Some combination of these two
In all cases you'll also have to deal with the vector's object slicing problem, by using pointers, or, even better, std::unique_ptr or std::shared_ptr, and having a vector of those.
Thank you for the inspiration.
I have a working solution posted below.
No implementation in the base class so it is now only a virtual function holder so a little bit of code bloating incurred.
Not sure if this solution will incur some caveat down the road but at least I have something working for my initial needs.
Many Thanks for the help.
#include <iostream>
#include <string>
#include <vector>
class Base {
public:
virtual void getStructInfo(int&, int&, std::uintptr_t&) = 0;
};
class Foo1 : public Base {
public:
struct Data {
std::string s1;
std::string s2;
std::string s3;
};
std::vector<Data> myData;
void getStructInfo(int& _sizeof, int& _count, std::uintptr_t& _address) {
_sizeof = sizeof(Data);
_count = myData.size();
_address = (std::uintptr_t)myData.data();
}
};
class Foo2 : public Base {
public:
struct Data {
int i1;
double d2;
bool b3;
};
std::vector<Data> myData;
void getStructInfo(int& _sizeof, int& _count, std::uintptr_t& _address) {
_sizeof = sizeof(Data);
_count = myData.size();
_address = (std::uintptr_t)myData.data();
}
};
class Top {
public:
std::vector<Base*> foos;
void test() {
int size;
int count;
std::uintptr_t address;
for (std::vector<Base*>::iterator f = foos.begin(); f != foos.end(); f++) {
(** f).getStructInfo(size, count, address);
std::cout << "Data Size = " << size << " Count = " << count << " Address=" << std::to_string(address) << std::endl;
}
}
};
int main(int argc, char* argv[])
{
std::cout << "Test Begin" << std::endl;
Foo1 f1;
Foo1::Data f1d;
f1d.s1 = "hello1";
f1d.s2 = "hello2";
f1d.s3 = "hello3";
f1.myData.push_back(f1d);
f1d.s1 = "goodbye1";
f1d.s2 = "goodbye2";
f1d.s3 = "goodbye3";
f1.myData.push_back(f1d);
Foo2 f2;
Foo2::Data f2d;
f2d.i1 = 10;
f2d.d2 = 1.9;
f2d.b3 = true;
f2.myData.push_back(f2d);
Top t;
t.foos.push_back(&f1);
t.foos.push_back(&f2);
t.test();
std::cout << "Test End" << std::endl;
}
result =
Test Begin
Data Size = 120 Count = 2 Address=1886816049088
Data Size = 24 Count = 1 Address=1886816032176
Test End
I am working with template class A<widget_type> and I want to know if it is possible to dynamic_cast<A<another_type>*>(A<widget_type>*).
Question: in the following code, A<B>* target2 = dynamic_cast<A<B>*>(&source); returns a null pointer. Is it possible to cast a template class into the same class but with another template?
Edit: I have to make a program where an array holds A<B*> objects, but A<B*> objects may come from A<C*> or A<D*>. I need to check at run-time if the A<B*> can be casted into the desired template class. I can't use strong-typing for that reason, since A<B*> object may come from an A<E*> object, where E is a class that other people may create and thus, there may not be a conversion function into that template class.
Code:
template<typename widget_type>
class A
{
public:
std::vector<widget_type*> value;
virtual ~A() {}
void Add(widget_type* val)
{
value.push_back(val);
}
template<typename return_type>
operator A<return_type>()
{
unsigned int size = this->value.size();
std::vector<return_type*> return_value;
return_value.resize(size);
for (unsigned int i = 0; i < size; i++)
{
return_value[i] = dynamic_cast<return_type*>(this->value[i]);
}
A<return_type> target;
target.value = return_value;
return target;
}
};
class B
{
public:
virtual ~B() {}
};
class C : public B
{
public:
void Print()
{
std::cout << "C CALL\n";
}
};
class D : public B
{
};
int main()
{
std::cout << "Start!\n";
A<C> source;
C* val1 = new C;
source.Add(val1);
A<B> target = source;
A<B>* target2 = dynamic_cast<A<B>*>(&source);
if (target2)
{
std::cout << "POINTER\n";
}
std::cout << "END\n";
}```
dynamic_cast will only succeed if there is some kind of inheritance relation between where you are coming from and where you are going to.
If you simply want to treat a pointer of one type as a pointer to a different type (which in general is true of different specializations of the same template) then dynamic_cast will not succeed. Only a c-style or reinterpret_cast will allow the cast but even then the results are not defined.
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";
}
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;
}