Ok, this example is pretty straight-forward for the concept I'm trying to understand. I'll just show you the code:
class Base
{
protected:
string name;
public:
virtual string getName() const { return this->name; }
virtual void setName(string name) { this->name = name; }
....
}
class Derived : public Base
{
private:
double price;
....
}
main(int argc, char** argv)
{
Base* base = new Base("Base Class");
Derived* derived = new Derived(base, 453.21);
derived->setName("Name changed!");
cout << "Name of instance: " << base->getName() << endl;
// Desired effect
Output: 'Name changed!'
// Actual effect
Output: 'Base Class'
....
}
The issue for me is this. I want to create an instance of derived class with reference to already created instance of base class, so when I change any member variable of base class trough the derived instance, I can see the change on previously created base instance in the way demonstrated above.
Note: I hope that you will manage to comprehend what I meant, as I am aware that my terminology is probably little off. Please, don't be harsh. :)
Note: I won't be showing / writing constructors, since I am not sure what is the best way to do this, if even any exists and the syntax may be incorrect.
This seems to indicate the problem:
Base* base = new Base("Base Class");
Derived* derived = new Derived(base, 453.21);
as it is usually not necessary to construct the Base class separatly. Your derived class will already contain a Base instance implicitly, you don't have to add a pointer to one manually and set it from the ctor. I don't know how your ctor looks, but it should look like this:
Derived(const std::string& name, double p) : Base(name), price( p ) {}
If this enough to fix it yourself, good, otherwise post all the code of your example. Instead of the two lines from your code that I quoted above, it should look more like:
Derived* derived = new Derived("Base Class", 453.21);
If you post the code of Derived, it should be obvious for us and it will be much easier to explain it to you on your concrete example.
The way you are trying to do is weird, but you can simply use inheritance concept like this code:
class Base
{
public:
Base(const string &name) : name(name) {}
virtual void setName(const string &name) { this->name = name; }
virtual string getName() const { return name; }
protected:
string name;
};
class Derived : public Base
{
public:
Derived(const string &name, double price) : Base(name), price(price) {}
private:
double price;
};
int main()
{
Derived* derived = new Derived("Base Class", 453.21);
derived->setName("Name changed!");
Base *base = derived;
cout << "Name of instance: " << base->getName() << endl;
}
Output
Name of instance: Name changed!
You don't need a create Base object and pass it to the derived object.
Instead, create a derived object and pass its address to a Base pointer.
Related
I'm new to OOP and I'm working on a C++ project. I isolated my problem to make answering easy but here's the real scenario:
I have a superclass member function, that modifies values inside the object that called it. The modification is based on a value coming from another object of the same class. This object is given to the function as the only parameter. Such as:
void BaseClass::function(BaseClass x) {}
However, I created a subclass. And if the parameter is a subclass type, I want to modify its unique attribute, too.
void BaseClass::function(DerivedClass x) {}
The problem is that the subclass is obviously defined later in the code.
I don't want it as two separate methods, because the calculation algorithm is already written inside, and also the solution I search for doesn't require to change the code at the places where the function is already in use. Besides, every other possibility that comes to mind (e.g. using typeid()) looks silly.
#include <iostream>
#include <string>
class Base
{
protected:
//common attribute
const std::string name;
public:
//constructor for common attribute
Base(const std::string nameString) : name(nameString) {}
//getter
std::string getName() { return name; }
//superclass as parameter
void test1(Base &example) { std::cout << example.getName(); }
//subclass as parameter (I'd want the line below to work)
//void test2(Derived &example) { std::cout << example.getNumber(); }
};
class Derived : private Base
{
protected:
//unique attribute
const std::string number;
public:
//constructor
Derived(const std::string nameString, const std::string numberString) : Base(nameString),
number(numberString) {}
//getter for unique attribute
std::string getNumber() { return number; }
};
int main ()
{
Base object = Base("whatever");
Base baseParameter = Base("base");
Derived derivedParameter = Derived("derived", "12");
object.test1(baseParameter);
//object.test2(derivedParameter);
return 0;
}
What is the standard way of doing it?
You could make test2 a template, and ensure that it's only used with types derived from Base:
template<typename Derived>
void test2(Derived &example)
{
static_assert(std::is_base_of_v<Base, Derived>);
std::cout << example.getNumber();
}
Here's a demo.
I know this might look like a trivial question, but I haven't found really an elegant C++ solution to the following problem.
I want to represent a complex (tree-like) hierarchy of a "world" of objects. Let's say Animals. Every animal has some basic const properties.
Like for example a name. Then it also has some methods, but they are not significant for this problem.
class Animal {
public:
const char *GetName() const;
protected:
const char *name;
};
class Insect : public Animal {
...
};
class Butterfly : public Insect {
...
};
In this hierarchy I would like to initialize the name in every derived (grand)child. What is an elegant solution to this?
It is also important to say that in this "world" there be only instances of the tree leaves. That is, there will be no objects "Animal" or "Insect". But there will be objects "Butterfly", "Bee" or "Mosquito".
I know the "standard" way to do this is to put name into constructor:
Animal::Animal(const char *name) : name(name) {}
Insect::Insect(const char *name) : Animal(name) {}
Butterfly::Butterfly() : Insect("Butterfly") {}
But if there are more of these properties, the derived classes need also some initialization and the hierarchy has more levels it can become quite a mess:
Animal::Animal(const char *name) : name(name) {}
Vertebrate::Vertebrate(const char *name) : Animal(name) {}
Mammals::Mammals(const char *name) : Vertebrate(name) {}
Ungulate::Ungulate(const char *name) : Mammals(name) {}
Horse::Horse() : Ungulate("Horse") {}
Another option I can see is to drop the const and assign directly in the grandchild's constructor:
class Animal {
public:
const char *GetName() const;
protected:
std::string name;
};
Horse::Horse() {this->name = "Horse";}
But that is also not optimal, because the const is lost and it is more prone to errors (the initialization can be forgotten).
Is there some better way to do this?
Hm - hope that I get not locked out from SO for that answer, but you could use a virtual base class that implements the name-property. Thereby, you will not have to propagate initialization in a base class all way through the hierarchy but could directly address the "very base" constructor with the name-property. Furthermore, you will actually be enforced to call it in any "Grandchild"-class, so you can't forget it by accident:
class NamedItem {
public:
NamedItem(const char* _name) : name(_name) {}
const char *GetName() const;
protected:
const char *name;
};
class Animal : public virtual NamedItem {
public:
Animal(int mySpecificOne) : NamedItem("") {}
};
class Insect : public Animal {
public:
Insect(int mySpecificOne) : Animal(mySpecificOne), NamedItem("") {}
};
class Butterfly : public Insect {
};
The elegant solution is to pass arguments through initialisation. For example, if the "name" variable was the name of the Butterfly (such as "sally" or "david") then it would be obvious it has to be done through initialisation. If you are finding that is ugly, as it is here, it may indicate that your data decomposition/class heirarchy are at fault. In your example every Butterfly object would have an identical set of properties that really refer to their class rather than each instance, ie they are class variables not instance variables. This implies that the "Butterfly" class should have a static pointer to a common "Insect_Impl" object (which might have a pointer to a single "Animal_Impl" object etc) or a set of overridden virtual functions. (Below I only show one level of heirarchy but you should be able to work out more levels)
// Make virtual inherited functionality pure virtual
class Animal {
private:
std::string objName; // Per object instance data
public:
virtual ~Animal(std::string n): objName(n) {}
virtual std::string const& getName() = 0; // Per sub-class data access
virtual std::string const& getOrder() = 0; // Per sub-class data access
std::string const& getObjName() { return this->objName; }
};
// Put common data into a non-inherited class
class Animal_Impl{
private:
std::string name;
public:
Animal_Impl(std::string n): name(n);
std::string const& getName() const { return this->name; }
};
// Inherit for per-instance functionality, containment for per-class data.
class Butterfly: public Animal{
private:
static std::unique< Animal_Impl > insect; // sub-class data
public:
Butterfly(std::string n): Animal(n) {}
virtual ~Butterfly() {}
virtual std::string const& getName() override {
return this->insect->getName(); }
virtual std::string const& getOrder() override {
static std::string order( "Lepidoptera" );
return order; }
};
// Class specific data is now initialised once in an implementation file.
std::unique< Animal_Impl > Butterfly::insect( new Animal_Impl("Butterfly") );
Now using the Butterfly class only needs per-instance data.
Butterfly b( "sally" );
std::cout << b.getName() << " (Order " << b.getOrder()
<< ") is called " << b.getObjName() << "\n";
The issue with your alternative, or any alternative leaving name non-const and protected, is that there is no guarantee that this property is going to be setup properly by the subclasses.
What does the following class give you ?
class Animal {
public:
Animal(const char* something)
const char *GetName() const;
private:
const char *name;
};
The guarantee of the immutability of the Animal interface, which can be a big plus when doing multithreading. If an object is immutable, multiple threads can use it without being a critical resource.
I know the "standard" way to do this is to put name into constructor:
... But if there are more of these properties, the derived classes
need also some initialisation and the hierarchy has more levels it can
become quite a mess
It is not messy at all. Given that there is only one place where the members of object A are being initialised, and it is within the constructor of their subclasses.
I am getting an issue for retrieving BaseClass correct enum value.
class BaseClass
{
public:
enum EntityId {
EN_NONE = 0,
EN_PLAYER = 1,
EN_PLATFORM,
EN_GROUND,
EN_OBSTACLE,
EN_OTHER
};
void setEntityId(EntityId id) { _Entityid = id; }
EntityId getEntityId() { return _Entityid; }
protected:
EntityId _Entityid;
};
and
class DeriveredClassA : public SomeClass, public BaseClass {....};
class DeriveredClassB : public SomeClass, public BaseClass {....};
The initialization goes like this
DeriveredClassA->setEntityId(BaseClass::EntityId::EN_PLAYER);
DeriveredClassB->setEntityId(BaseClass::EntityId::EN_OBSTACLE);
Which is placed into a different vector list correspoinding to that enum.
However, I am forced to use void* to do static_casts cats...
Like this:
BaseClass* EA = static_cast<BaseClass*>(bodyUserDataA); //bodyUserDataA and bodyUserDataB are both void*
BaseClass* EB = static_cast<BaseClass*>(bodyUserDataB);
And I am trying to retrieve using EA->getEntityId() and EB->getEntityId() so I could check which one is EN_PLAYER, which one is EN_GROUND and etc. So then I could up-class from base into derivered class and do other stuff with it.
Tried using with virtual, however somehow I am receiving 2 copies of _EntityID, which can be either the same or DIFFERENT between my Derivered and BaseClass of that one object.
Moreover, I can't cast right away into DeriveredClass, since the code checking would be huge, due to many different types of DeriveredClass'es (DeriveredClassA, DeriveredClassB, DeriveredClassC, DeriveredClassD) with their corresponding vector list.
My question is that How I need setup correctly both Base and Derivered class, so that I could access _EntityID from Baseclass which is the same of that DeriveredClass? My main problem might is that I used incorectly virtual functions, so I left on default to understand my issue.
P.S. This is mainly my c++ issue, other tags are added due to I am using game engine and physics engine for this case.
I believe that you want your code to look more like this:
class Entity
{
public:
enum Type {
EN_NONE = 0,
EN_PLAYER = 1,
EN_PLATFORM,
EN_GROUND,
EN_OBSTACLE,
EN_OTHER
};
Type getType() { return _type; }
protected:
Entity(Type type): _type(type) {}
private:
const Type _type;
};
Then your derived classes and usage of this base would be more like:
class PlayerEntity: public Entity, public SomeClass
{
public:
PlayerEntity(std::string name): Entity(EN_PLAYER), _name(name) {}
std::string getName() const { return _name; }
private:
std::string _name;
};
class PlatformEntity: public Entity, public SomeClass
{
public:
PlatformEntity(): Entity(EN_PLATFORM) {}
};
Initialization is then done like:
int main()
{
PlatformEntity platform;
std::vector<PlatformEntity> platforms(platform);
std::vector<PlayerEntity> players;
players.emplace_back("Bob");
players.emplace_back("Alice");
players.emplace_back("Ook");
}
Access from user-data could then look like this:
// bodyUserDataA and bodyUserDataB are both void*
Entity* const EA = static_cast<Entity*>(bodyUserDataA);
Entity* const EB = static_cast<Entity*>(bodyUserDataB);
switch (EA->getType())
{
case Entity::EN_PLAYER:
{
PlayerEntity* player = static_cast<PlayerEntity*>(EA);
std::cout << "Found player: " << player->getName();
break;
}
case Entity::EN_OTHER:
...
default:
break;
}
This question already has answers here:
Polymorphism in C++
(7 answers)
Closed 9 years ago.
From past few weeks I am learning and experimenting inheritance and Polymorphism in C++.
Few syntax always confusing me to understand, mainly object calling from main function.
for eg:
#include <iostream.h>
using namespace std;
class Base
{
public:
Base(){ cout<<"Constructing Base";}
virtual ~Base(){ cout<<"Destroying Base";}
};
class Derive: public Base
{
public:
Derive(){ cout<<"Constructing Derive";}
~Derive(){ cout<<"Destroying Derive";}
};
void main()
{
Base *basePtr = new Derive();
delete basePtr;
}
Here is my question:
What actually happens when Base *basePtr = new Derive(); this syntax is called? and what are the advantages?
As per my knowledge I understood it calls derive class object and stores it in a pointer to base class object. Am I correct? If I am, why are we storing it in base class?
To clear my doubts I went through memory layout of class objects and disassembling, but it confuses me more.
Could anyone tell me how to understand this kind of syntax?
Public inheritance means that every object of the derived class IS at the same time an object of the base class (it provides all the interfaces the base class has). So, when you write:
Base *basePtr = new Derive();
new object of class Derive is created, than the pointer to it is assigned to basePtr and through basePtr you can access all the functionality Base class provides.
And if you then call any of Base class virtual functions like:
basePtr->callSomeVirtualFunction();
the function from the actual object class will be invoked, as it happens with the destructor in the end of your main function.
When you are using pointer to a base class object instead of pointer to a derived one, you are saying that you need only BASIC properties of this derived class.
Hmmm... Pointers are confusing at the beginning.
When you call Base *basePtr = new Derive();, you are creating a Derive object instance and just keeping a "bookmark" of where this object is, but with a Base pointer.
When you do that, the only accessible properties (without a cast) will be from Base class.
Why this is used? To abstract things. Imagine that you are coding something related to mugs, cups, glasses and jugs. Basically all types of those objects are make to store some kind of liquid. So I'll call the base class of LiquidContainer:
class LiquidContainer
{
//...
};
class Mug : public LiquidContainer
{
//...
};
class Glass : public LiquidContainer
{
//...
};
class Cup : public LiquidContainer
{
//...
};
class Jug : public LiquidContainer
{
//...
};
All the others are inherited from LiquidContainer, although the Jug, the Cup and the Mug could be created in a little more sophisticated inheritance tree.
Anyway, the intent of having a base class and using polymorphism is to avoid code replication and to abstract thins, allowing that all the LiquidContainer family be treated almost the same way.
Take by example a more complete class definition.
class LiquidContainer
{
public:
LiquidContainer(unsigned int capacity, unsigned int color) :
mCapacity(capacity),
mColor(color)
{
}
unsigned int getCapacity() { return mCapacity; }
unsigned int getColor() { return mColor; }
virtual char* name() = 0;
protected:
unsigned int mCapacity;
unsigned int mColor;
};
class Mug : public LiquidContainer
{
public:
Mug() :
LiquidContainer( 250, 0xFFFF0000 ) // 250 ml yellow mug!
{
}
virtual char* name() { return "Mug"; }
};
class Glass : public LiquidContainer
{
public:
Glass() :
LiquidContainer( 200, 0x000000FF ) // 200 ml transparent glass!
{
}
virtual char* name() { return "Glass"; }
};
class Cup : public LiquidContainer
{
public:
Cup() :
LiquidContainer( 50, 0xFFFFFF00 ) // 50 ml white cup!
{
}
virtual char* name() { return "Cup"; }
};
class Jug : public LiquidContainer
{
public:
Jug() :
LiquidContainer( 1500, 0x0000FF00 ) // 1.5 l blue Jug!
{
}
virtual char* name() { return "Jug"; }
};
With those class definitions you could do the following test:
#include <iostream>
#include <vector>
int main( int argc, char* argv[] )
{
std::vector< LiquidContainer* > things;
things.push_back( new Mug() );
things.push_back( new Cup() );
things.push_back( new Glass() );
things.push_back( new Jug() );
for ( auto container : things )
{
std::cout << "This is a '" << container->name() << "' with capacity of " << container->getCapacity() << "ml and color " << container->getColor() << std::endl;
}
return 0;
}
This little program outputs
This is a 'Mug' with capacity of 250ml and color 4294901760
This is a 'Cup' with capacity of 50ml and color 4294967040
This is a 'Glass' with capacity of 200ml and color 255
This is a 'Jug' with capacity of 1500ml and color 65280
I hope that this little exercise are enough to show you why the polymorphism is used.
That's called Polymorphism. It means that the object is a Derive as well as Base and can be used as both. For eg. If Dog is the subclass of Animal. Object of dog can be treated as Animal too. All dogs are animal, but not all animals are dog.
So you can call a dog an animal, that's why you can give the address of subclass object(Derive) to superclass pointer(Base). But it'll remain an object of subclass and will function like one. This is just to fool compiler into understanding that it's an object of Base.
Now the benefit is you can have a method which can accept object(or pointer in precise sense) of Base class, but can be passed any of it's subclass. The con here is you can only call methods which are in the base class and may or may not overridden in derive class.
I am making a simple console game in C++
I would like to know if I can access members from the 'entPlayer' class while using a pointer that is pointing to the base class ( 'Entity' ):
class Entity {
public:
void setId(int id) { Id = id; }
int getId() { return Id; }
protected:
int Id;
};
class entPlayer : public Entity {
string Name;
public:
void setName(string name) { Name = name; }
string getName() { return Name; }
};
Entity *createEntity(string Type) {
Entity *Ent = NULL;
if (Type == "player") {
Ent = new entPlayer;
}
return Ent;
}
void main() {
Entity *ply = createEntity("player");
ply->setName("Test");
ply->setId(1);
cout << ply->getName() << endl;
cout << ply->getId() << endl;
delete ply;
}
How would I be able to call ply->setName etc?
OR
If it's not possible that way, what would be a better way?
It is possible by using a cast. If you know for a fact that the base class pointer points to an object of the derived class, you can use static_cast:
Entity* e = /* a pointer to an entPlayer object */;
entPlayer* p = static_cast<entPlayer*>(e);
p->setName("Test");
If you don't know for sure, then you need to use dynamic_cast and test the result to see that it is not null. Note that you can only use dynamic_cast if the base class has at least one virtual function. An example:
Entity* e = /* a pointer to some entity */;
entPlayer* p = dynamic_cast<entPlayer*>(e);
if (p)
{
p->setName("Test");
}
That said, it would be far better to encapsulate your class's functionality using polymorphism (i.e. virtual functions).
Speaking of virtual functions, your class hierarchy as implement has undefined behavior: you can only delete an object of a derived type through a pointer to one of its base classes if the base class as a virtual destructor. So, you need to add a virtual destructor to the base class.
I would consider doing something like this:
public:
void setId(int id)
{
Id = id;
}
void virtual setName( string name ) = 0; // Virtual Function
string virtual getName() = 0; // Virtual Function
int getId() { return Id; }
protected:
int Id;
};
class entPlayer : public Entity {
string Name;
public:
entPlayer() {
Name = "";
Id = 0;
}
void entPlayer::setName(string name) { // Must define function
Name = name;
}
string entPlayer::getName() { return Name; } // again must define function here
};
You can do a dynamic cast:
entPlayer * pPlayer = dynamic_cast<entPlayer *>(pointer_to_base);
This will (if successful) result in a derived pointer.
Otherwise NULL is returned.
C++ makes what you are trying to do really awkward, because this is probably not what you should be doing, and it is trying to lead you to good object-oriented design. In fact, by default, compilers often disable run-time type information (RTTI), which is needed to make dynamic_cast work.
Without knowing your broader context, it's hard to say what you should do instead. What I can say is that if you wanted a more specific pointer, you should have put a ring on it you almost certainly shouldn't use a function that returns an Entity*, and there is probably a better approach.