Is it possible to access the child's function members from a pointer of an abstract class as the parent?
This is the abstract class
class Item {
public:
virtual double getTotalPrice() = 0;
};
This is the child class
class Product : public Item {
protected:
string name;
public:
Product() {}
string getName() {}
double getTotalPrice() {}
};
Is it possible in the main driver to access this getName() function from an instance of the Item class, as I want to display the total price and the name of the product also?
You need your base class to have a virtual destructor if you should be able to delete objects through a base class pointer.
Make getName virtual too.
class Item {
public:
virtual ~Item() = default;
virtual const string& getName() /* const */ = 0;
virtual double getTotalPrice() /* const */ = 0;
};
Note that the Product class that you aren't allowed to change is slightly flawed.
It doesn't return values where it should.
The getter member functions are not const.
Suggest some changes if you can't do it yourself:
class Product : public Item {
private: // prefer private member variables
string name;
public:
Product() = default;
const string& getName() const override { return name; }
double getTotalPrice() const override {
// why is this implemented here when there's no price to return?
return {};
}
};
You cannot have an instance of the abstract Item class (because it's abstract) but you can have an Item pointer (or reference) to a derived (and non-abstract) Product class.
But because Item declares no getName() , you'd probably need to do a dynamic_cast to check if the pointee is really a Product, for ex.
Item* item = new Product();
...
// at same later time or some ooter function:
// use dynamic_cast to check if the pointee is the type you expect it to be
Product* p = dynamic_cast<Product>(item);
if (p) p->getName();
Though, not directly targeting your question I think there is also a design issue here. Something like Product conists of many items so it's rather 1:N composition relationship. For getting total price a concept (for ex. Billable ) would be mnore appropriate.
So I would probably advise something like following for the class hierarhy:
class Billable
{
public:
virtual double getTotalPrice() const = 0;
virtual ~Billable() {}
};
class Item : public Billable
{
string name;
public:
string getName() const { return name; }
double getTotalPrice() const override { ... impl .. }
// ... rest
}
class Product : public Billable
{
string name;
vector<Items> items;
public:
string getName() const { return name; }
double getTotalPrice() const override
{
return accumulate(begin(items), end(items), 0, [](auto i) { return i->getTotalPrice(); });
}
// ... rest ...
}
You can static cast if you're sure that the pointer points to an actual object of type Product or dynamic cast if you're not sure and want to check it first. This doesn't work if the pointer doesn't point to an object of the derived class.
class Item {
public:
virtual double getTotalPrice() = 0;
};
class Product : public Item {
protected:
string name;
public:
Product() {}
string getName() {return {};}
double getTotalPrice() {return {};}
};
int main() {
Product p;
Item *i = &p;
static_cast<Product *>(i)->getName();
auto *ptr = dynamic_cast<Product *>(i);
if (ptr) ptr->getName();
}
dynamic_cast requires runtime type information (RTTP) and comes with some extra costs.
Usually it's better to redesign the architecture instead of downcast.
Related
I have a class that is called Object, this class's header is:
class DLL_SPEC Object {
public:
Object();
virtual ~Object();
virtual std::string getString() const;
virtual void setString(std::string value);
virtual int getInt() const;
virtual void setInt(int value);
virtual double getDouble() const;
virtual void setDouble(double value);
virtual bool isType(FieldType type) const;
};
And my child classes are as follows:
class DLL_SPEC IntObject : public Object {
public:
IntObject() : value(0) {}
IntObject(int v) : value(v) {}
void setInt(int value) override { this->value = value; };
int getInt() const override { return this->value; };
bool isType(FieldType type) const override;
private:
int value;
};
class DLL_SPEC DoubleObject : public Object {
public:
DoubleObject() : value(0.0) {}
DoubleObject(double v) : value(v) {}
void setDouble(double value) override { this->value = value; };
double getDouble() const override { return this->value; };
bool isType(FieldType type) const override;
private:
double value;
};
class DLL_SPEC StringObject : public Object {
public:
StringObject() : value("") {}
StringObject(std::string v) : value(v) {}
void setString(std::string value) override { this->value = value; };
std::string getString() const override { return value; };
bool isType(FieldType type) const override;
private:
std::string value;
};
Now, the problem is, I have an array of Objects and I want to get a string representation of a StringObject.
I call array[0].getString() and even though the object is of type StringObject, the method that gets called is the one is the base class, which I understand.
So, how would I go about implementing that whenever I call getString() on the base class it goes to the child one of the SAME object?
I've tried using this method:
std::string Object::getString() const
{
return dynamic_cast<StringObject*>(this).getString();
}
but then I get an error stating I cannot cast away const or any type qualifier, which is fixed by deleting const modifier (which I MUST leave there as it's according to the task), but then I get another one stating that no suitable constructor exists. So how would I go about implementing this and getting this base class to use the one of the child one?
EDIT: Added a small example that goes into the getString method of Object class and not the StringObject class.
int findPersonId(std::string whereName)
{
Db* db = Db::open("database");
Table* people = db->openTable("table");
auto iteratorTable = table->select();
while (iteratorTable->moveNext())
{
for (size_t i = 0; i < table->getFieldCount(); i++)
{
if (table->getFields()[i]->getName() == "id")
{ //this one beneath goes to the base class and not StringObject
std::string foundRow = iteratorPeople->getRow()[i]->getString();
if (foundRow == whereName)
{
return iteratorTable->getRowId();
}
}
}
}
return 0;
}
Note: The Table* is 2D array that consists of Object** (array that contains StringObject, IntObject, DoubleObject). The method .getRow() return the Object** array that consists of StringObject ...
The way I initiate the objects that go into the array is
Table* table= db->openOrCreateTable("table", 2, userFields); //this creates a 2d array
StringObject* name = new StringObject("Joseph");
IntObject* id = new IntObject(5);
Object** row = combineToRow(id, name);
table->insert(row); //insert an array into 2D array
The method combineToRow is just a simple convertor to Object**.
template<typename A, typename B>
Object** combineToRow(A a, B b) {
return new Object * [2]{ a, b };
}
You have not implemented a getString method for your IntObject, and since you didn't override it you are calling the base method. Once you implement it like this
class IntObject : public Object {
...
virtual std::string getString() const { return std::to_string(value); };
...
};
then you can call it.
int main(){
StringObject* name = new StringObject("Joseph");
IntObject* id = new IntObject(5);
Object** row = combineToRow(id, name);
std::cout << row[0]->getString() << " " << row[1]->getString();
}
5 Joseph
See working version here
I Have two classes:
First:
class Thing {
public:
int code;
string name;
string description;
int location;
bool canCarry;
Thing(int _code, string _name, string _desc, int _loc, bool _canCarry) {
code = _code;
name = _name;
description = _desc;
location = _loc;
canCarry = _canCarry;
}
};
Second:
class Door: public Thing {
private:
bool open;
public:
int targetLocation;
Door(int _code, string _name, string _desc, int _loc, int _targetLoc) :
Thing(_code, _name, _desc, _loc, false) {
open = false;
targetLocation = _targetLoc;
}
void Use() {
open = true;
}
void Close() {
open = false;
}
bool isOpen() {
return open;
}
};
Forget private/public atributes...
I need to store some objects of base class and some objects of derived class,
something like this:
vector < Thing*> allThings;
things.push_back(new Thing(THING1, "THING1", "some thing", LOC1, true));
things.push_back(new Door(DOOR1, "DOOR1", "some door", LOC1, LOC2));
But in this case, functions Use(), Open(), and isOpen() will not be reachable because of slicing..
Do you have some suggestions, how to store these objects together without creating new structure of vector<Thing*> and vector<Door*>??
Thanks
A good solution to a problem when you need a container of objects with polymorphic behavior is a vector of unique pointers:
std::vector<std::unique_ptr<Thing>>
There would be no slicing in this situation, but you would have to figure out when it's OK to call Use(), Open(), and isOpen().
If you can move the methods from the derived class into the base, go for it; if you cannot do that because it makes no sense for a Thing to have isOpen(), consider using a more advanced solution, such as the Visitor Pattern:
class Thing;
class Door;
struct Visitor {
virtual void visitThing(Thing &t) = 0;
virtual void visitDoor(Door &d) = 0;
};
class Thing {
...
virtual void accept(Visitor &v) {
v.visitThing(*this);
}
};
class Door : public Thing {
...
virtual void accept(Visitor &v) {
v.visitDoor(*this);
}
}
Store pointers instead of instances, and declare public and protected methods as virtual in the base class(es).
I am trying to define an interface called "Algorithm" which has a pure virtual method insertData(InputData* input).
The implementation of the interface is called "Algorithm1" and i want to implement method "insertData" using as a parameter "SpecificData" which is a child of "InputData" class.
Is it possible without type casting?
Obviously with this code i get an error from the compiler that the virtual function "insertData" is pure within "Algorithm1".
class Algorithm{
public:
virtual ~Algorithm();
virtual void insertData(InputData* input) = 0;
};
class Algorithm1 : public Algorithm{
public:
Algorithm1();
virtual ~Algorithm1();
void insertData(SpecificData* input){
input.getID();
input.getAdditionalNumbers;
/*Process input information etc.*/ };
};
class InputData{
public:
void setID(int id){ this->id = id; }
int getID(){ return id;};
private:
int id;
};
class SpecifiData : public InputData{
public:
list<int> getAdditionalNumbers(){/*Return various Numbers*/};
private:
list<int> extraInfo;
};
void main(){
SpecificData* data = new SpecificData();
Algorithm* alg = new Algorithm1();
alg->insertData(data);
}
For insertData to be the same function (rather than "hiding" the original insertData, you need the two functions to have the same arguments (and same return type).
The whole idea of interfaces using virtual functions is that "they appear the same from the outside". You should be able to build a list of objects, and perform the same operation with the same input data for all of the objects in the list.
If you are breaking that principle, you are "doing it wrong".
No, it wouldn't make sense.
Think about the following scenario - you have a container (vector/set w/e) of Algorithm* type objects and a function that takes this container and a InputData* in as an input and then iterate over them and call insertData(in) on each of the objects in the container, this of course should work properly, but if one of the objects in your container is of type Algorithm1 what will happen then?
I think, this is a typical example of "Factory Method" in design pattern term.
class Algorithm
{
public:
virtual ~Algorithm();
virtual void insertData(InputData* input) = 0;
};
class InputData
{
public:
void setID(int id){ this->id = id; }
int getID(){ return id;};
virtual list<int> getAdditionalNumbers() = 0;
private:
int id;
};
class Algorithm1 : public Algorithm
{
public:
Algorithm1();
virtual ~Algorithm1();
void insertData(InputData* input){
input.getID();
input.getAdditionalNumbers;
/*Process input information etc.*/ };
};
class SpecifiData : public InputData
{
public:
// implementation
virtual list<int> getAdditionalNumbers(){/*Return various Numbers*/};
private:
list<int> extraInfo;
};
void main()
{
InputData* data = new SpecificData();
Algorithm* alg = new Algorithm1();
alg->insertData(data);
}
I think I messed up somehow in my design because I want to keep a vector of various object types. These types all share a common base class. Example:
Class Buick: AmericanCar
{
}
Class Ford: AmericanCar
{
}
then I did:
vector<AmericanCar*> cars_i_own;
Now, I have my vector of pointers but I don't have the derived class which is what I need. I thought about adding a GetType/SetType function to the base class and then use a dynamic cast. This is clunky though. Did i use the wrong design for this?
Well, what are you trying to do with it? Get the name or cost? You would have something like:
class Car
{
public:
virtual ~Car(void) {}
virtual std::string location(void) const = 0;
virtual std::string name(void) const = 0;
virtual double cost(void) const = 0;
}
class AmericanCar
{
public:
virtual ~AmericanCar(void) {}
virtual std::string location(void) const
{
return "America";
}
}
class Buick : public AmericanCar
{
public:
virtual std::string name(void) const
{
return "Buick";
}
virtual double cost(void) const
{
return /* ... */;
}
}
class Ford : public AmericanCar
{
public:
virtual std::string name(void) const
{
return "Ford";
}
virtual double cost(void) const
{
return /* ... */;
}
}
Now you can call these methods polymorphically.
This is somewhat strange, though. You don't need a different class to store names and cost like this:
class Car
{
public:
Car(const std::string& pLocation,
const std::string& pName,
double pCost) :
mLocation(pLocation),
mName(pName),
mCost(pCost)
{
}
const std::string& location(void) const
{
return mLocation;
}
void location(const std::string& pLocation)
{
mLocation = pLocation;
}
const std::string& name(void) const
{
return mName;
}
void name(const std::string& pName)
{
mName = pName;
}
const double cost(void) const
{
return mCost;
}
void cost(double pCost)
{
mCost = pCost;
}
private:
std::string mLocation;
std::string mName;
double mCost;
}
// make cars
std::vector<Car> cars;
cars.push_back(Car("America", "Buick", /* ... */));
The purpose of inheritance / polymorphism is so you don't need to care which derived type you are dealing with.
In particular I think storing data, such as make of car, country of origin etc, encoded in a class hierarchy doesn't seem to be particularly beneficial. Does an AmericanCar do something fundamentally different from, say, a Japanese car (other than consuming more fuel, which again can be better stored in a data member)?
Why do you need to know the derived class? Normally you would have virtual functions to take care of any behavior differences between the two derived classes.
The goal is that the code using the parent class shouldn't have to know the exact class it's working with.
You can use typeid to determine the derived class:
struct Base
{
virtual ~Base() {}
};
struct Derived : public Base { };
int main()
{
Base* b = new Derived();
std::cout << typeid(*b).name() << std::endl;
}
This outputs: "Derived".
But, usually with polymorphism the point is that you shouldn't be concerned with this. You simply call a base-class member function and the proper derived-class member function is called at runtime.
Is there anyway to have a sort of virtual static member in C++?
For example:
class BaseClass {
public:
BaseClass(const string& name) : _name(name) {}
string GetName() const { return _name; }
virtual void UseClass() = 0;
private:
const string _name;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass("DerivedClass") {}
virtual void UseClass() { /* do something */ }
};
I know this example is trivial, but if I have a vector of complex data that is going to be always the same for all derived class but is needed to be accessed from base class methods?
class BaseClass {
public:
BaseClass() {}
virtual string GetName() const = 0;
virtual void UseClass() = 0;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() {}
virtual string GetName() const { return _name; }
virtual void UseClass() { /* do something */ }
private:
static const string _name;
};
string DerivedClass::_name = "DerivedClass";
This solution does not satify me because I need reimplement the member _name and its accessor GetName() in every class. In my case I have several members that follows _name behavior and tenths of derived classes.
Any idea?
Here is one solution:
struct BaseData
{
const string my_word;
const int my_number;
};
class Base
{
public:
Base(const BaseData* apBaseData)
{
mpBaseData = apBaseData;
}
const string getMyWord()
{
return mpBaseData->my_word;
}
int getMyNumber()
{
return mpBaseData->my_number;
}
private:
const BaseData* mpBaseData;
};
class Derived : public Base
{
public:
Derived() : Base(&sBaseData)
{
}
private:
static BaseData sBaseData;
}
BaseData Derived::BaseData = { "Foo", 42 };
It seems like the answer is in the question - the method you suggested seems to be the right direction to go, except that if you have a big number of those shared members you might want to gather them into a struct or class and past that as the argument to the constructor of the base class.
If you insist on having the "shared" members implemented as static members of the derived class, you might be able to auto-generate the code of the derived classes. XSLT is a great tool for auto-generating simple classes.
In general, the example doesn't show a need for "virtual static" members, because for purposes like these you don't actually need inheritance - instead you should use the base class and have it accept the appropriate values in the constructor - maybe creating a single instance of the arguments for each "sub-type" and passing a pointer to it to avoid duplication of the shared data. Another similar approach is to use templates and pass as the template argument a class that provides all the relevant values (this is commonly referred to as the "Policy" pattern).
To conclude - for the purpose of the original example, there is no need for such "virtual static" members. If you still think they are needed for the code you are writing, please try to elaborate and add more context.
Example of what I described above:
class BaseClass {
public:
BaseClass(const Descriptor& desc) : _desc(desc) {}
string GetName() const { return _desc.name; }
int GetId() const { return _desc.Id; }
X GetX() connst { return _desc.X; }
virtual void UseClass() = 0;
private:
const Descriptor _desc;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass(Descriptor("abc", 1,...)) {}
virtual void UseClass() { /* do something */ }
};
class DerDerClass : public BaseClass {
public:
DerivedClass() : BaseClass("Wowzer", 843,...) {}
virtual void UseClass() { /* do something */ }
};
I'd like to elaborate on this solution, and maybe give a solution to the de-initialization problem:
With a small change, you can implement the design described above without necessarily create a new instance of the "descriptor" for each instance of a derived class.
You can create a singleton object, DescriptorMap, that will hold the single instance of each descriptor, and use it when constructing the derived objects like so:
enum InstanceType {
Yellow,
Big,
BananaHammoc
}
class DescriptorsMap{
public:
static Descriptor* GetDescriptor(InstanceType type) {
if ( _instance.Get() == null) {
_instance.reset(new DescriptorsMap());
}
return _instance.Get()-> _descriptors[type];
}
private:
DescriptorsMap() {
descriptors[Yellow] = new Descriptor("Yellow", 42, ...);
descriptors[Big] = new Descriptor("InJapan", 17, ...)
...
}
~DescriptorsMap() {
/*Delete all the descriptors from the map*/
}
static autoptr<DescriptorsMap> _instance;
map<InstanceType, Descriptor*> _descriptors;
}
Now we can do this:
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass(DescriptorsMap.GetDescriptor(InstanceType.BananaHammoc)) {}
virtual void UseClass() { /* do something */ }
};
class DerDerClass : public BaseClass {
public:
DerivedClass() : BaseClass(DescriptorsMap.GetDescriptor(InstanceType.Yellow)) {}
virtual void UseClass() { /* do something */ }
};
At the end of execution, when the C runtime performs uninitializations, it also calls the destructor of static objects, including our autoptr, which in deletes our instance of the DescriptorsMap.
So now we have a single instance of each descriptor that is also being deleted at the end of execution.
Note that if the only purpose of the derived class is to supply the relevant "descriptor" data (i.e. as opposed to implementing virtual functions) then you should make do with making the base class non-abstract, and just creating an instance with the appropriate descriptor each time.
I agree with Hershi's suggestion to use a template as the "base class". From what you're describing, it sounds more like a use for templates rather then subclassing.
You could create a template as follows ( have not tried to compile this ):
template <typename T>
class Object
{
public:
Object( const T& newObject ) : yourObject(newObject) {} ;
T GetObject() const { return yourObject } ;
void SetObject( const T& newObject ) { yourObject = newObject } ;
protected:
const T yourObject ;
} ;
class SomeClassOne
{
public:
SomeClassOne( const std::vector& someData )
{
yourData.SetObject( someData ) ;
}
private:
Object<std::vector<int>> yourData ;
} ;
This will let you use the template class methods to modify the data as needed from within your custom classes that use the data and share the various aspects of the template class.
If you're intent on using inheritance, then you might have to resort to the "joys" of using a void* pointer in your BaseClass and dealing with casting, etc.
However, based on your explanation, it seems like you need templates and not inheritance.
#Hershi: the problem with that approach is that each instance of each derived class has a copy of the data, which may be expensive in some way.
Perhaps you could try something like this (I'm spit-balling without a compiling example, but the idea should be clear).
#include <iostream>
#include <string>
using namespace std;
struct DerivedData
{
DerivedData(const string & word, const int number) :
my_word(word), my_number(number) {}
const string my_word;
const int my_number;
};
class Base {
public:
Base() : m_data(0) {}
string getWord() const { return m_data->my_word; }
int getNumber() const { return m_data->my_number; }
protected:
DerivedData * m_data;
};
class Derived : public Base {
public:
Derived() : Base() {
if(Derived::s_data == 0) {
Derived::s_data = new DerivedData("abc", 1);
}
m_data = s_data;
}
private:
static DerivedData * s_data;
};
DerivedData * Derived::s_data = 0;
int main()
{
Base * p_b = new Derived();
cout getWord() << endl;
}
Regarding the follow-up question on deleting the static object: the only solution that comes to mind is to use a smart pointer, something like the Boost shared pointer.
It sounds as if you're trying to avoid having to duplicate the code at the leaf classes, so why not just derive an intermediate base class from the base class. this intermediate class can hold the static data, and have all your leaf classes derive from the intermediate base class. This presupposes that one static piece of data held over all the derived classes is desired, which seems so from your example.