Array of base abstract class containing children class in C++ - c++

so I have a Top class, let say:
//Top.h
#pragma once
#include <string>
using std::string;
class Top
{
protected:
string name;
public:
virtual string GetName() = 0;
}
This class won't have any object Top instantiate, that's why it's an abstract class. I also have two Middle class, let say:
//MiddleA.h
#pragma once
#include "Top.h"
class MiddleA : public Top
{
protected:
int value;
public:
MiddleA(string, int);
string GetName();
int GetValue();
}
//MiddleB.h
class MiddleB : public Top
{
protected:
double factorial;
public:
MiddleB(string, double);
string GetName();
double GetFactorial();
double Calculate(int);
}
Now, what I need is an array, or anything, that can contains multiple objects of type MiddleA, MiddleB or any classes that inherit from those two classes. Is there a way to do this in C++?
EDIT : Would it be "acceptable" to add a default constructor in the protected section and use a vector or array of Top?

Use the pointers and arrays of C++:
typedef std::array<std::unique_ptr<Top>,3> Tops;
Tops tops =
{{
new MiddleA( "Kuku", 1337 ),
new MiddleB( "Hoi", 42.0 ),
new MiddleC()
}};
Only thing you have to have virtual destructor on your Top. Without virtual destructor you may only use shared_ptr, others will result with undefined behavior when objects are destroyed.

yes. You could do it this way.
Top* array[3] = { new Top(parms), new MiddleA(params), new MiddleB(params) };
but you will be only able to call GetName() function. You wouldnt be able to call other methods.

Related

Accessing subclass methods in array of pointers

I've been having trouble accessing the "getDegreeProgram()" method in my objects that are set to my array of pointers; all of my baseclass methods are working, but for some reason, my subclass methods aren't even visible. I'm suspecting that I don't have the syntax right, and its converting all of my subclass objects to the baseclass of student.
roster.h:
class roster {
private:
student** classRosterArray; //array of pointers
roster.cpp function that creates my objects and sets them to the array of pointers
void roster::createStudentObject() {
classRosterArray = new student *[5]; //array of pointers
if (degreeProgramInput == "NETWORK") {
classRosterArray[rosterCounter] = new networkStudent();
}
else if (degreeProgramInput == "SECURITY") {
classRosterArray[rosterCounter] = new securityStudent();
}
else classRosterArray[rosterCounter] = new softwareStudent();
}
student.h subclasses in question (they're subclasses of my baseclass "student")
class networkStudent:public student {
private:
int networkDegree;
public:
int getDegreeProgram();
networkStudent();
};
class securityStudent:public student {
private:
int securityDegree;
public:
int getDegreeProgram();
securityStudent();
};
class softwareStudent:public student {
private:
int softwareDegree;
public:
int getDegreeProgram();
softwareStudent();
};
As far as I understood, you are trying to access the elements of classRosterArray and trying to call getDegreeProgram().
For this problem, Make the getDegreeProgram() virtual function.
student.h
class student {
...
public:
virtual int getDegreeProgram() = 0; // pure virtual function
};
Subclasses of student
class networkStudent:public student {
private:
int networkDegree;
public:
virtual int getDegreeProgram();
networkStudent();
};
class securityStudent:public student {
private:
int securityDegree;
public:
virtual int getDegreeProgram();
securityStudent();
};
class softwareStudent:public student {
private:
int softwareDegree;
public:
virtual int getDegreeProgram();
softwareStudent();
};
Suggestion:
In this case, Because getDegreeProgram() seems to be a getter function, I think you should declare it as a const function.
Edit:
As rightly said by Richard, In C++ 11, override keyword was introduced for this purpose for the sub classes. So, instead of writing virtual int getDegreeProgram();, you could write int getDegreeProgram() override; also.
There are two you ways you can go about it.
Runtime Polymorphism - This method will require less code refactoring but at the cost of runtime. Each instance of a polymorphic class will have a pointer(vptr) to a table(vtable) of pointers to the different versions of the virtual function. This table will be used for finding the right version of the virtual function at runtime.
You can achieve runtime polymorphism here by making the getDegreeProgram function virtual in base class ie., Student and override it in derived classes ie., securityStudent, networkStudent and softwareStudent.
class Student {
...
public:
virtual int getDegreeProgram() = 0; // notice the virtual keyword and 0 at the end.
// 0 is for saying that it is pure virtual, meaning
// we don't have any definition for this function in
// this class. Such a class is also called as
// abstract class
...
}
class securityStudent : Student {
...
public:
int getDegreeProgram() override
{
// do the stuff you want to do
}
...
}
// driver stub
...
Student *student;
securityStudent sStudent;
networkStudent nStudent;
.
.
student = &sStudent;
student->getDegreeProgram(); // calls security student implementation of getDegreeProgram
student = &nStudent;
student->getDegreeProgram(); // calls network student implementation of getDegreeProgram
...
Static Polymorphism or CRTP or Simulated Dynamic Binding - This method does the same thing as above but with the advantage of knowing the type at compile time by means of some casting magic (below). Even this approach has its limitation like kludgy syntax and some amount of refactoring which is a lot more than in the 1st case and lack of readability due to terseness of templates etc.
The trick here is to get the derived class' information at compile time and typecast the this pointer of the base class to that of the derived class. :-)
template <typename StudentType>
class Student {
...
public:
int getDegreeProgram()
{
return (static_cast<StudentType*>(this))->getDegreeProgramImpl();
}
...
}
class securityStudent : public Student<securityStudent> {
...
public:
int getDegreeProgramImpl()
{
// write your specifc implementation here
}
...
}
// driver stub
...
securityStudent sStudent;
networkStudent nStudent;
.
.
sStudent.getDegreeProgram(); // calls security student implementation of getDegreeProgram
nStudent.getDegreeProgram(); // calls network student implementation of getDegreeProgram
...

Can you set pointer to derived class after you set some values in the base class?

I am new to c++ (I am using visual studio 2013) and I started experimenting with classes and inheritance. So I came up with a question which I can not find any anwser. Lets say we have this class:
#include <iostream>
using namespace std;
class base{
protected:
int var;
public:
void setvalue(int);
virtual void print();
};
class first:public base{
public:
void print();
};
class second: public base{
public:
void print();
};
Is there a way I can declare in my main() a pointer to base, set the value and after that choose if it is a first or second class? Ex:
int main(){
base *ptr = new base;
ptr->setvalue(1);
/* Here I choose if base is pointing to First or Second class*/
ptr->print(); // use the correct member, based on which class I choosed
return 0;}
Is this somehow possible? (As I said I am new to c++ so in case you have any questions, feel free to ask!)
Thanks!
Since it's not possible, the only thing that comes to mind is that you solve your problem in another way, perhaps using some well common design pattern.
In this case, given the little information you gave, Factory pattern seems appropriate.
#include <iostream>
using namespace std;
class base {
protected:
int var;
public:
void setvalue(int);
virtual void print();
static base* makeObject(int);
};
class first : public base {
public:
void print();
};
class second : public base {
public:
void print();
};
base* base::makeObject(int param) {
base* ret = NULL;
if(/* some condition based on params */) {
ret = new first();
ret->setvalue(0);
} else if(/* some other condition */) {
ret = new second();
ret->setvalue(1);
}
return ret;
}
int main() {
base *ptr = base::makeObject(...);
base->print(); // use the correct member, based on which class I choosed
return 0;
}
The type of an object is fixed at construction and can never be changed. So the direct answer to your question is "no".
But within that framework you have a lot of power. For example, you could separate your three classes out into four: three that do just do printing (BasePrinter, DerivedPrinter1, DerivedPrinter2) and other that just holds the value and doesn't have any virtual methods. Your BasePrinter class could get passed a ValueHolder object (by const reference) every time you call the print() method. Alternatively, each ValueHolder could have a pointer to BasePrinter object and pass in all the necessary data each time, with a little (non-virtual) print() method to do all this forwarding.
Not directly. When you create an object, you need to specify its full type so that C++ knows how to correctly lay out memory for you.
If you actually need to change it later, you can always create a new class (of the correct derived type) and use the original base class to initialize it, then delete the original. This might be slightly slower than the method you were proposing (depending on the final complexity of the class), but it would get the job done.
Since you are using inheritance , it is best practice to define virtual destructor in your base class. It will take care proper clean up when you define complicated class.
int main(){
base *ptr = new base;
base->setvalue(1);
/* Here I choose if base is pointing to First or Second class*/
base->print(); // use the correct member, based on which class I choosed
return 0;}
What you are trying to do is not possible. You have to change your program as follows to avoid compilation error.
base *ptr = new base;
ptr->setvalue(1);
ptr->print();
delete ptr;
return 0;
Because you base pointer ptr always have the dynamic type of class base. this code always invoke base::print function
If you define ptr as follows, you can utilize the polymorphism.
base * ptr = new first;
ptr->setvalue(1);
ptr-> print()
delete ptr
Here ptr has a dynamic type of class first and it will call function first::print()
You have to choose type at the creation of the object:
int main()
{
base *ptr = new first; // here.
ptr->setvalue(1);
ptr->print(); // use first::print.
delete ptr;
}

Inheritance between two classes in c++ using the same data members and functions

I'm new to C++ programming and I want to create two classes that have the exact same data members and functions. Is it possible to create two inherited classes that have the same data members/functions instead of making several duplicate methods for each class. I'm making a c++ game based on zork and I want to create two items, weapons and fruits. Both will take in a name as a string and a value as a double. Do I create the header file as below:
#ifndef ITEM_H_
#define ITEM_H_
#include <map>
#include <string>
#include <iostream>
using namespace std;
class Item {
private:
string description;
string longDescription;
float value;
public:
Item (string description, float inValue);
Item (string description);
string getShortDescription();
string getLongDescription();
float getValue();
void setValue(float value);
};
class Weapon:: public Item{
};
class Fruit:: public Item {
};
#endif /*ITEM_H_*/
How would I no go about creating the methods without duplicating them?
Do nothing for now. Both Weapon and Fruit are Items and contain all the members and methods that Item does.
Sooner or later, you'll want to specialize behaviour of child classes and the implementation of the method in the base class won't do it (if it's sensible to have an implementation in the first place). This is where polymorphism comes in. You'll make the method in the base class virtual and override it in the derived class:
class Item {
public:
virtual void Use() = 0; // pure virtual method
};
class Weapon : public Item {
public:
virtual void Use() override
{
Fire();
}
private:
void Fire() { /* do something */ }
};
Now when you have a reference or a pointer to the base class and you call Use on it, it'll dispatch to the corresponding method in the derived class.
EDIT: There's no way around "duplicating" constructors. Each class needs at least one if it is ever to be instantiated. Since you declared Item (string description, float inValue); you need to define it as a member of Item, too:
Item (string description, float inValue)
: description(description) // <-- avoid duplicating names of members in parameter list,
, value(inValue) // it does the right thing, but hurts readability
{ /* body empty */ }
If you need to call the constructor of the derived class with same parameters, you need to define another constructor and forward the arguments to the constructor of base class:
Weapon::Weapon(string desc, float val)
: Item(desc, val) { }
In C++11, there's a shortcut - you can inherit constructors and the compiler will generate these forwarding constructors for you:
class Weapon : public Item {
using Item::Item;
};
There's (unfortunately, perhaps) no way to specify which constructors you want to inherit. It's all or nothing.
Hope that helps.
you need to call constructor of parent class to assign value to description; and longDescription; like
class Weapon:: public Item{
Weapon(string description, float inValue):Item(description,inValue){}
Weapon(string description):Item(description){}
};

C++: Polymorphism

I want to start by showing some code and explain my problem later.
Base class:
class swcObject :
public swcRectangle
{
public:
bool visible;
};
Sub-base class[optional, abstract]:
class swcText
{
public:
std::string text;
protected:
virtual void attachedToParent() = 0;
};
Derived classes:
class swcLabel :
public swcObject,
public swcText
{
public:
int text_align;
private:
void attachedToParent();
};
...
class swcComboBox :
virtual protected swcObject
{
public:
void setPosition(int x, int y);
private:
swcLabel label;
};
Now I have this class w/c has a member object of type std::vector<swcObject>.
class swcWindow :
private swcObject
{
public:
void addObject(const swcObject &object);
private:
std::vector<swcObject> objects;
};
I came into this few problems w/c I haven't encountered before and Google seems don't have a relevant problem like mine.
My specific problems are:
Relevant code:
swcWindow window;
swcComboBox cbox;
window.addObject(cbox);
Error:
'swcObject' is an inaccessible base of 'swcComboBox'
Desire:
I do not want to access swcComboBox::swcObject members on public scope like this cbox.x = 0;, but instead cbox.setPosition(0, 0); because there will be always an adjusting of some member elements whenever the swcComboBox had changed its location.
Relevant code:
swcWindow window;
swcLabel label;
window.addObject(label);
Error:
In this case, label have a base classes of swcText and swcObject. After adding the label to one of member of window.objects (is of type std::vector), swcText properties are gone, like the text property.
Desire:
I want to create a temporary objects and initialize its property in a init() method outside of those classes and copy it using swcWindow::addObject(). Is this possible without a cast? I think this one would do but its awful(?), and I didn't try it yet if this is working:
void addObject(const swcObject &object, SWC_TYPES type)
{
switch (type)
{
case LABEL:
//do casting?
...
}
}
Please recommend any other way how can I achieve those kind of implementation with the same functionalities.
vector store elements by value, as if you passed your ComboBox to a procedure which takes a swcObject by value, not by reference. This leads to cut of object to its base class, which is prohibited if you use protected inheritance.
You shouldn't store polymorphic objects in vector, just as you shouldn't pass them by value. You can try storing references or (smart) pointers in vector - that should solve your problems.

Passing object into array that are of the same parent class

As I am still somewhat new to programming in C++ I was just curious if it were possible to pass objects pointers to an array in order for code consolidation.
Header file like such;
class.h
class parent
{
some information.....
};
class child1 : public parent
{
some information.....
};
class child2 : public parent
{
some information.....
};
Main file like such;
main.cpp
#include "class.h"
int main()
{
child1 instanceChild1;
child2 instanceChild2;
child1* pointer1 = &instanceChild1;
child2* pointer2 = &instanceChild2;
parent array[2] = {pointer1 , pointer2};
}
I am trying to achieve such so that I may create a function that uses a dynamic array in order to hold object pointers so that I may dereference them in the function and manipulate them accordingly. Though I am having issues getting the different pointers to work together when going into an array. I need such functionality since there will be many different objects(all under the same parent) going in and out of this function.
Yes it is possible.
But you need to declare the array like this
parent * arr[] = { ... }
or it would be better if you use a vector
vector<parent *> arr;
arr.push_back(childPointer);//For inserting elements
as #pstrjds and #basile has written
and if you want to use child specific member functions, you can use dynamic cast
ChildType1* ptr = dynamic_cast<ChildType1*>(arr.pop());
if(ptr != 0) {
// Casting was succesfull !!! now you can use child specific methods
ptr->doSomething();
}
else //try casting to another child class
** your compiler should support RTTI in order for this to work correctly
you can see this answer for details
I prefer to use pure Virtual functions like this
class A {
public :
enum TYPES{ one , two ,three };
virtual int getType() = 0;
};
class B : public A{
public:
int getType()
{
return two;
}
};
class C : public A
{
public:
int getType()
{
return three;
}
};