Upcast using reference in C++ - c++

I would like to use the "Strategy" design pattern, and have just one simple question.
We have two classes: Base as an abstract class and Derived as a concrete class.
#include <iostream>
using namespace std;
class Base {
public:
virtual void func() = 0;
};
class Derived : public Base{
public:
virtual void func() override
{
printf("hello \n");
}
};
int main(){
Base * base = new Derived();
base->func();
Derived derived2;
Base & base2 = derived2;
base2.func();
return 0;
}
Using pointer,
Base * base = new Derived();
Using reference
Derived derived2;
Base & base2 = derived2;
Is there any way to write in one line for reference?
Which method are you guys use to implement the "strategy" design pattern,
using pointer or reference?
Because of the reason above, I tend to use pointer... but I would like an answer from experts.

Is there any way to write in one line for reference?
You could use static_cast<Base&>. This produces a reference to the Base portion of your object :
int main() {
Derived derived2;
static_cast<Base&>(derived2).func();
return 0;
}
Which method are you guys use to implement the "strategy" design pattern, using pointer or reference?
You don't usually see references used for this because most of the time you need to store your polymorphic object and that's not practical with references. References refer to an object, but that object needs to otherwise exist somewhere else.
Notice that your first case creates a dynamically allocated instance, you can pass the pointer around easily. The second one creates a local object which is much harder to move around polymorphically. If you try to store your Derived object into a container, you'll certainly need to dynamically allocate it anyway. Trying to do otherwise will result in object slicing (where the derived portion is entirely sliced off).
For example, this is how you would store a Derived into a container of Base pointers :
int main()
{
std::vector<std::unique_ptr<Base>> my_bases;
my_bases.emplace_back(std::make_unique<Derived>());
}
If you tried to use a std::vector<Base> it wouldn't compile (Base is abstract). But even if it did compile (by making Base concrete) it would not behave polymorphically. This is not unique to the strategy pattern. This is how it works whenever you employ polymorphism.

Related

Copy contents of unique_ptr to unknown derived class

I have an abstract base class, with several concrete derived classes; none of these classes manage any resources.
#include <memory>
#include <vector>
// this is a pure abstract class that contains no resources
class Base {
public:
Base() {};
virtual int doSomething() = 0;
};
class Derived : public Base {
public:
Derived() {};
// this mutates the derived class
int doSomething() override { return 0; };
};
class Derived2 : public Base {
public:
Derived2() {};
// this mutates the derived class
int doSomething() override { return 0; };
};
and I have a function that returns a random derived instance (Derived1, Derived2, Derived3, depending upon a random number throw).
std::unique_ptr<Base> randomDerivedInstance() {
// pick a random number here and return Derived1 or Derived2 etc.
// for the purpose of this problem, I'm just returning a fixed derived class
return std::make_unique<Derived>();
}
and I have a struct that I want to store this derived instance in
struct DataStruct {
// this can contain Derived1 or Derived2
std::unique_ptr<Base> base;
// other things in struct omitted for clarity
// obviously this won't work
DataStruct(std::unique_ptr<Base> base) : base(base) {};
};
I return a unique pointer from my random function, and want to save a copy into the struct, and then call doSomething on it that performs several mutating operations on the class internals, and I don't want them to affect the copy stored in the list.
If I knew the type of the derived instance, I would use a copy constructor to create a new instance and add it to the vector, but in this situation I don't know the specific type of the instance I'm trying to add, so I don't know which specific constructor to use.
int main() {
// I want to create a vector of random instances
std::vector<DataStruct> list;
// I create a random instance
auto myDerived = randomDerivedInstance();
// and I want to push a copy of myDerived before I do something with it
// obviously this doesn't work because its a unique_ptr
// what can I do here?
list.push_back(DataStruct(myDerived));
// do something that mutates myDerived
myDerived->doSomething();
// I don't want my mutations to myDerived to affect the list copy
}
The code above doesn't compile for obvious reasons since I'm trying to assign a unique_ptr in the DataStruct constructor.
What changes do I need to make to this architecture and code in order to get this to work as intended? i.e. add a value-copy of random derived instance to a struct, so that I can mutate the original instance (or vice-versa, add original, and mutate copy).
Thanks for all help in advance!
In class Base add a virtual member function clone:
virtual auto clone() const
-> std::unique_ptr<Base>
= 0;
In each derived class Derived override that to provide a derived class specific clone:
auto clone() const
-> std::unique_ptr<Base>
override
{ return std::unique_ptr<Base>( new Derived{ *this } ); }
It's possible to do this in a more advanced way where if you know the most derived class at compile you can get a clone statically of that type, but it doesn't appear that you need that.
Disclaimer: off-the-cuff code, not reviewed by compiler.
At one time, long ago, a clone function was called a virtual constructor, and that term is used in the FAQ item about this. I think it was introduced by Coplien. The current FAQ text doesn't say.
Also worth noting: in C++11 and later the generation of clone function implementations can be partially automated by Derived inheriting from an implementation that in turn inherits from Base, with forwarding of constructor arguments.
C++03 didn't support forwarding so then one had to use schemes such as code-generating macro (evil but in practice the only real solution back then), implementation inheritance via dominance in a virtual inheritance hierarchy (extremely complex and ugly), or to do the same as we now can do in C++11 and later, but with a Do-It-Yourself argument forwarding scheme (somewhat arbitrary limited).
For an overview of these old C++03 techniques see my 2010 blog article “3 ways to mix in a generic cloning implementation”.

Call an interface function from an unknown derived class (multiple inheritance)

I have an array of Base* objects. This holds a bunch of derived objects, some of which may implement an Interface.
struct Base {
virtual void doNotCallThis() { cout << "nooo" << endl; }
};
struct Interface {
virtual void doThis() = 0;
};
// Example derived class
struct Derived : Base, virtual Interface {
virtual void doThis() { cout << "yes" << endl; }
};
int main() {
Base* b[1];
b[0] = new Derived(); // Here would be a bunch of different derived classes
((Interface*)b[0])->doThis(); // Elsewhere, doThis() would be called for select array elements
return 0;
}
Output:
nooo
I don't know the exact type of b[i] at run time, so I can't cast to Derived (it could be Derived2, Derived3, etc). I also can't use dynamic_cast if that's a solution. All I know is that, by the time I call doThis(), b[i] is a type that inherits from Interface. The way I attempted to call it above causes the wrong function to be called, eg. Base::doNotCallThis().
How can I call it properly?
As other people have pointed out, you would probably do best to find a way to refactor your design so that casting isn't necessary.
But putting that aside, I can explain what's going wrong and how to correctly cast.
The problem with ((Interface*)b[0]) is that since Base and Interface are unrelated the compiler has to do a blind reinterpretive cast. Practically speaking that means in this situation the resulting pointer doesn't actually line up with the Interface part of the object. If you were to try static_cast<Interface*>(b[0]) you would find it doesn't compile - and that's a big hint that it's the wrong kind of cast to be making.
On the other hand, the compiler does know the relationship from Base to Derived and also from Derived to Interface. So as long as you know for sure that the object not only implements Interface but also is a Derived then you can do:
static_cast<Interface*>(static_cast<Derived*>(b[0]))->doThis();
However if your design has multiple different derived types which independently implement Interface then you might not be able to do that unless again you absolutely know what the derived type is at any time you go to make the call. - This is why refactoring it into a better class hierarchy is more desirable, since it's much less fragile and cumbersome to work with.
(As a side note, this issue points out why it's a great idea to never use raw/reintrepretive casts when moving up and down a class hierarchy. At least use static_cast since the can compiler better help you do it correctly.)
Writing an answer with the risk of being downvoted:
If we start with::
struct Base()
{
virtual void SomeFunc();
};
struct Interface
{
virtual void doThis();
}
then to create a bunch of derived functions from Base that are also interfaces, I'd do something like this:
struct BaseInterface : public Base, public Interface
{
// Nothing here - this is just combining Base and Interface
};
struct Base1 : public BaseInterface
{
... add stuff that Base1 has that isn't in Base.
};
struct Derived: public Base1
{
... some more stuff that isn't in Base1
}
And then we use it in Main like this:
int main() {
BaseInterface* b[1];
b[0] = new Derived(); // Here would be a bunch of different derived classes
b[0])->doThis(); // Elsewhere, doThis() would be called for select array elements
return 0;
}

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;

extending base class by casting it to derived and setting the data

Assume I have this:
class Base {
public:
int a;
Base() : a(5) {}
};
template<class T>
class Derived : public Base {
public:
T value;
};
The code below works but I want to know what can be the challenges of using such approach:
Base * base = new Base;
Derived<int> * derived = static_cast<Derived<int>*>(base);
derived->value = 5;
Derived<String> * derived1 = static_cast<Derived<String>*>(base);
derived1->value = "test";
Derived<String> * newderived = static_cast<Derived<String>*>(base);
std::cout << newderived->value;
Derived<int> * newderived1 = static_cast<Derived<int>*>(base);
std::cout << newderived1->value;
//Output: test1
Or how can I achieve such thing in a different, safer way. I want to pass a class through 5 functions that will manipulate it.
What you're doing here will fail horribly at some point because the size of the derived class is larger than the base class and you write after the end of the base class. The above write operation will overwrite memory that belongs to another object.
You can have a SetValue() method in the base class and implement it in the derived class.
The code does not work. All you objects even after casting are still a Base because you constructed them as a base. The casts just say: Hey, I know it's a Derived<xxx>, so please just interpret that this way. You don't know this here, in fact you know it is NOT a Derived.
To properly use the objects, you need to create a Derived<xxx> and afterwards cast. If you use a dynamic_cast here all cases should come back as null as they are Base.
Given that you wanted to "pass a class through 5 functions" you'd probably want the inverted setup. Create Derived<xxx> objects and hold them as a pointer to Base. This works without casting as it should. Then pass the Base* through your functions. Polymorphism will take care that everything works fine.

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();