Vector in an abstract class - c++

I believe that the question here is similar however I still need more clarification on it.
Let's say I create a vector inside an abstract class (which stores objects of another class). How would I be able to use .pushback() from another class if I can't initialise an object of an abstract class?
Obviously the easiest solution is to put the vector in another class but I need another way. I've read you can do this by storing pointers to those objects in a vector. But can somebody give me an example please?

The purpose of an abstract class is to provide an interface that is then implemented in concrete derived classes.
If you want to push items onto the vector which is a data member of the abstract class, then create an appropriate derived class and then you can create an instance of that derived class, which will thus contain a vector you can add entries to.
class Base{
public:
virtual void do_stuff()=0; // this is an abstract base class
protected:
std::vector<int> data;
};
class Derived: public Base
{
public:
void do_stuff() {
// concrete implementation
data.push_back(42); // can add values to vector inherited from base class
}
};
int main()
{
Derived d;
d.do_stuff(); // will add entries to d.data
}
However, I wonder if that is really what you are trying to achieve.

I could find some existing SO answers, but they were using C++98 code.
The right way to store a vector of abstract base classes, in that base class , is to have a vector of smart pointers to the abstract base class.
First, add the vector, and a virtual destructor
struct AbstractBase {
virtual ~AbstractBase(); // <-- this makes sure these shenanigans don't cause memory leaks
std::vector<std::unique_ptr<AbstractBase>> children;
};
Then push_back new derived classes:
struct Derived1 : public AbstractBase; // defined elsewhere
/*...*/
base.children.push_back(std::make_unique<Derived1>());
//or
auto child = std::make_unique<Derived1>();
base.children.push_back(std::move(child));
It has to be a vector of pointers allocated on the heap because vector doesn't know from the base class how big the derived classes are to store them directly.
It has to be a vector of smart pointers because when you're using pointers and heap allocation, someone has to be responsible for cleaning them up. Smart pointers do that automatically.
Lastly, that virtual destructor there in the abstract base class makes sure that even when you're using pointers that have been casted down to abstract base classes, it will call the right destructor to clean everything up.

Related

Why on macos with clang I can create vector of base class objects

To describe my problem, I will assume that we have:
abstract class Base (with few pure virtual functions).
classes A, B and C. All inherited from Base. All override pure virtual functions from Base.
Now the problem is in ways to create vector, that can store any of A, B or C object.
Well, I know, that I need to create vector of pointers to base class object, like:
std::vector<Base*> list;
But my friend with Apple M1 and clang able to create vector of base class objects (without using pointer) and all fine in his environment. Code:
std::vector<Base> list;
It is very strange for me. I was assuming, vector store objects with equal size per each of them. So all objects in vector must be of the same type, and with pointer all fine, but how it works with instances?
I checked this situation on clang and M1 again and checked code of my friend. I have found a problem place, he didn't actually define pure virtual functions, just empty virtual functions in Base class, like here:
class Base {
public:
virtual void function() {}
}
In this case, object slicing works fine, because we can instantiate Base class. And, of course, we also able to create vector of Base class objects and put there objects of derived class.
std::vector<Base> list;
A a; // A class here is derived from Base
list.push_back(a);

inheritance of an implemented class

This is probably a simple question, please bear with me since I'm used to Java...
Lets say we have an interface:
class IDoable {
virtual void do() = 0;
};
Another class:
class Base : public IDoable {
//...
virtual void do() { ... }
};
And a last class extending our base class:
class ExtendingBase : public Base {
// some extra functionality
};
I am lost at the part if I want to make a list of IDoable objects, which can be Base objects or ExtendingBase objects. Do I have to add some method declaration of the methods in the Base class? How does this aspect work?
EDIT:
I have someList of type IDoable pointers
and if I then try to add a Base object to that list I get the error:
IDoable is an ambiguous base of Base
Same if i try to add an ExtendingBase object
IDoable is an ambiguous base of ExtendingBase
Since do is a pure virtual method, it will have to be implemented in a derived class. You can't have a vector or array of IDoable objects because you can't instantiate such an object. You can have a vector or array of pointers or references to objects though.
If you create an ExtendingBase object and call the do function, it will call the Base class' one (since ExtendingBase inherits that method).
Virtual polymorphism enters into play when you call the do() function from a base class pointer or reference: the do() function appropriate to the dynamic type of the object pointed or referenced to will be called:
class IDoable{
public:
virtual void dof()=0;
virtual ~IDoable() = default;
};
class Base:public IDoable{
public:
virtual void dof(){std::cout << "Base";}
virtual ~Base() = default;
};
class ExtendingBase:public Base{
public:
virtual void dof() { std::cout << "ExtendingBase"; }
};
int main()
{
IDoable *ptr = new Base(); // A smart pointer would be a better choice
// but for clarity's sake I'm using bare
// memory allocations here
ptr->dof(); // Walks the virtual table and calls "Base"
delete ptr;
ptr = new ExtendingBase();
ptr->dof(); // Walks the virtual table and calls "ExtendingBase"
delete ptr;
}
Also notice the use of virtual destructors: they work like normal virtual functions and thus when calling delete on a base pointer, in order to actually destruct the right type of object (i.e. to call the right destructor in the hierarchy), you will need to make it virtual.
As a sidenote: do is a reserved keyword in C++
In response to your edit: if you have a vector or a list of IDoable pointers, you can't just add a derived object to it, but you should add a pointer to a derived object. I.e. the following is wrong:
std::vector<IDoable*> vec;
vec.push_back(Base());
plus a base class remains a class (there is no interface concept in C++ as in Java) and you shouldn't inherit from a base class multiple times:
class Base:public IDoable{
...
class ExtendingBase:public Base, public IDoable <- nope
...
that would only cause issues in identifying the base subobject.
I recommend to read about the dreaded diamond problem in C++ (it's a way to solve a base class appearing multiple times in the inheritance hierarchy.. anyway a good design might probably avoid this in the first place).
if I want to make a list of IDoable objects
You cannot make an IDoable object period. It's an abstract class, it cannot be constructed directly, so you cannot have a container of them. What you can do and what you likely intend is to have a container of IDoable*:
std::vector<IDoable*> objects;
objects.push_back(new Base);
objects.push_back(new ExtendedBase);
Or to express ownership better in C++11:
std::vector<std::unique_ptr<IDoable>> objects;
Given your interface, you can already call do() on any of these objects and that will do the right thing via virtual dispatch. There is one member function you definitely want to add to your interface though:
class IDoable {
public:
virtual ~IDoable() = default; // this one
virtual void do() = 0;
};
That way, when you delete an IDoable*, you will delete the full object, not just the base interface.
You will have to implement your do() function in Base, since the function in the class IDoable is pure virtual.
If you decide to create an ExtendingBase object, the do() function will behave as it's implemented in Base, unless you override it by re-implementing it in ExtendingBase.
the first and most major of your problem is that your thinking in Java.
the words "interface" and "extending" are very Java oriented. C++ does not think this way.
for example, when someone talks about an "interface" in a C++ context, I may think he talks about the class decleration inside the .h file (as opposed to the implementation which lies in the .cpp file)
IDoable is a CLASS. period. the only difference is that it has a pure virtual functions that prohibits instansiation. other than that it behaves as a class, it can be inherited from, can hold member variables and anything else.
you just need to make sure the abstract function is overriden in some derived class in order for that class to produce objects.
thus said :
//in the stack:
Base base;
ExtendingBase eBase;
base.do();
eBase.do()
//in the heap with IDoable as pointer:
IDoable * base = new Base();
IDoable * ebase = new ExtendingBase ();
base->do();
ebase->do();
now, you may ask - how do I activate Base and ExtendingBase functions? so just like Java, you need to cast the pointer and only then call the right function.
Base* realBase = (Base*)base;
realbase->someBaseFunction();
as many things in C++, this code is a bit dangerous. you can use dynamic_cast instead.
and one last thing - do is a keyword in C++, it cannot declare a function name.
IDoable *pDo1 = new Base();
IDoable *pDo2 = new ExtendingBase();
pDo1->do();
pDo2->do();
delete pDo1;
delete pDo2;

C++ copy constructor issue with parent/child classes

I've run into a problem with copy constructors...I assume there is a basic answer to this and I'm missing something obvious - maybe I'm doing something entirely wrong - but I haven't been able to figure it out.
Basically, I have a parent class and child class. The parent class contains a vector of pointers to a (different) base class object. The child class wants to instead store pointers to objects derived from that base object.
Here's a pseudocode sample, if that helps:
// Base classes
class ItemRev {
...
}
class Item {
protected:
vector<ItemRev *> m_revPtrVec;
}
Item::Item(const Item &inputItemObj)
{
// Copy contents of the input object's item rev pointer vector
vector<ItemRev *>::const_iterator vecIter = (inputItemObj.m_revPtrVec).begin();
while (vecIter != (inputItemObj.m_revPtrVec).end()) {
(this->m_revPtrVec).push_back(new ItemRev(**vecIter));
}
}
=========
// Derived classes
class JDI_ItemRev : public ItemRev {
...
}
class JDI_Item : public Item {
...
}
JDI_Item::JDI_Item(const JDI_Item &itemObj)
{
// Copy contents of the input object's item rev pointer vector
vector<ItemRev *>::const_iterator vecIter = (inputItemObj.m_revObjPtVec).begin();
// The below does not work!
while (vecIter != (inputItemObj.m_revObjPtVec).end()) {
m_revObjPtVec.push_back(new JDI_ItemRev(**vecIter));
}
}
The problem with the above is in the push_back() call in the JDI_Item copy constructor.
Given this setup, what should the child class's copy constructor look like? Do I even need a child class copy constructor? I assumed I did, because the copy constructor is creating new objects, and the parent copy constructor will create new objects that are not the type I want in the derived class (i.e., the parent object stores pointers to ItemRev objects, while the child object should store pointers to derived JDI_ItemRev objects).
As mentioned in the comments, there is probably a more succinct way to express this problem (i.e. your class structure needs some work).
However, if you want to do it this way, the easiest way to achieve it is to use a virtual clone() method in the base class of ItemRev, with overrides of it defined in derived classes.
e.g.:
class ItemRev {
virtual ItemRev* clone() const = 0;
};
class JDI_ItemRev : public ItemRev {
ItemRev* clone() const override
{
// do your actual cloning here, using the copy constructor
return new ItemRev(*this);
}
};
Now, whenever you call clone() on any class derived from ItemRev, you will be returned an ItemRev* but it will point to a fully constructed derived class. You can of course get to the derived class's interface with static_cast<> or dynamic_cast<>.
...however...
derivation often seems like an easy win but it often turns out not to be. Inheritance should only be used if the derived class really is a type of the base class. Often people select inheritance when the derived class is a lot like a base class, or shares many characteristics with a base class. This is not the time to use inheritance. It's the time to use encapsulation.
In general, inheritance is evil.
On another note, you might find this link interesting.
Presentation on inheritance as an implementation detail

Use existing base class object when allocating a derived class

I need help with a specific programming problem in C++ (not sure if this is even possible in C++). I need to be able to access all public member functions in Base class, but do not want to allocate memory for the Base class data while allocating the Derived class object.
Lets say, I have:
class Base
{
public:
Base();
~Base();
int GetFoo() { return foo; }
// other public member functions of Base class
private:
int foo;
// other data
};
class Derived : public Base
{
public:
Derived(Base *BasePtr);
Derived(Base &BaseRef);
~Derived();
double GetXyz() { return xyz; }
// other public member functions of Derived class
private:
double xyz;
// other data
};
Now, lets say I already have a Base class allocated and initialized. I want to create a new Derived class object by referring to that existing Base object and allocate memory only for the data specific to the Derived class. Following the above example, I would have already allocated memory for "int foo" in the Base class object and only want to allocate memory for "double xyz" in the Derived class object.
Base *basePtr = new Base();
Derived *derivedPtr = new Derived(basePtr); // what is the content of this function?
What should be the memory allocation or the constructor for the Derived class look-like? I want to inherit all data and member functions of the Base class, but without doing a "combined" data allocation of Base and Derived. I have tried overloading operator new but no luck. Any help is appreciated.
I'm not sure if it fits your requirements, but you could simply copy the contents of the Base stored in basePtr inside a new Derived object, then delete the Base object and point at the new Derived object with the old Base pointer. Like this:
Base *basePtr = new Base();
/* Do something with base here */
Derived *derivedPtr = new Derived(basePtr);
delete basePtr;
basePtr = derivedPtr;
derivedPtr = 0;
That way you'll end up with only one object (of type Derived) and won't have to store a separate pointer to it, nor store the Base object, and that seems like what you need.
Update:
in my case, I cannot delete the Base object since I would have created millions of them (using GigaBytes of RAM space) and people could be using pointers/references to those objects, so copying them to Derived objects and deleting the old Base objects doesn't work for me.
In that case, maybe you should try to do an "extendable* structural wrapper. First create an simple class without any method or member:
class Additional{};
Then create a wrapper structure:
struct wrapper{
Base *basePtr;
Additional *moreInfo;
}
Then, instead of deriving your Derived class from Base, derive it from Additional. And instead of storing milions of Base pointers, store milions of wrapper pointers. IT'll make your code a bit longer and harder to understand, but it'll do what you need. Well - unless the only thing your Derived class adds is a pointer or any data that takes less size.
If you've got virtual functions in Base, in order to use them with the new hierarchy, oyu'll just have to check every time:
wrapper *wrapperPtr = &alreadyCreatedSomewhereWrapper;
if(wrapperPtr->moreInfo)
wrapperPtr->moreInfo->function();
else
wrapperPtr->basePtr->function();
Use multiple inheritance.
class Base()
class Derive1() : Base
class Derive2() : Base
class MostDerive() : Derive1 , Derive2
MostDerived() will be thin. Derive1 and Derive2 will need to be deterministically constructed, but that can be imposed, or some Init() functions can be used.

linking vector of derived class type to vector of parent class type in C++

I am in beginner stage of C++. Suppose I have a base class and a derived class:
class Base{
....
}
class Derived:public Base{
....
}
Now I have two vectors as follows, I will perform some operations to some create base and derived objects and push these objects back to their corresponding vectors respectively:
std::vector<Base*> baseVector
std::vector<Derived*> derivedVector
I want to point each of the element(object) of derivedVector to each of the element(object) of the baseVector. Suppose derivedVector[2] will have a pointer to baseVector[2] so that at any time I can access the base object from my derived object. How should I do this?
It's not very clear what you mean, but if I understand correctly you want to put pointer to your Derived object in two vectors. You can achieve it this way:
baseVector[2] = derivedVector[2] = new Derived();
I think this is the important part of your question:
... so that at any time I can access the base object from my derived object.
And the answer is fairly simple. With inheritance, the derived object can already access its base object. That's the whole point of inheritance.
You can keep it simple:
class Base{
SomeBaseFunction();
}
class Derived : public Base{
// Do not add a Base* here.
}
int main() {
Derived *derived_object = new Derived();
derived_object->SomeFunction(); // this works.
}
You should think more clearly about your vectors here. You probably only need one vector, not two. Also, you should probably deal with vector<Derived>, not vector<Derived*>.
int main () {
Derived derived_object; // don't use `new` here, it's just awkward
vector<Derived> vector_of_objects;
vector_of_objects.push_back(derived_object);
}
In modern C++, whether you're a beginner or an expert, you shouldn't use * or new very often.
See if you want to use base list to contain derived object pointers then it is ok. but you can't use derived list to hold base pointers.
may be you want something like.
Base * pBase = new Base();
Derived *pDerived_1 = new Derived();
// or
Base *pDerived_2 = (Base *)new Derived();
// this can be anytime casted back
Derived *pDerived_3 = (Derived*)pDerived_2;
// you can also push them into base vector
lstBasePtr.push_back(pBase);
lstBasePtr.push_back(pDerived_1);
lstBasePtr.push_back(pDerived_2);
lstBasePtr.push_back(pDerived_3);
Hi thanks for your response. I have figured out what I needed to do. Not sure if its the smartest way, if not please suggest me.
Here is how I did it:
class Base{
SomeBaseFunction();
}
class Derived:public base{
//I have put a pointer of base type here
base *basePointer;
}
Now in the main function where I basically populate the base and derived vector, I do the following:
derivedObject->basePointer = baseObject;
Now I can access the base properties as follows:
derivedObject->basePointer->SomeBaseFunction();