using smart pointers in a derived class constructor - c++

The question, at the outset: (preface: new to c++ oop programming)
How do I construct a derived class, Widget, such that I have a vector of (shared?) pointers in terms the base class, where the original objects (such that they are still of the derived class) can be accessed upon casting and dereferencing the pointers?
Say I have a base class:
class Component {
public:
int a;
int b;
virtual void rtti(){}; // for run time type information.
explicit Component(int a, int b) { this->a = a; this->b = b;}
}
And two derived classes,
class AComponent:public Component{
public:
using Component::Component;
AComponent(int a, int b) : Component(int a, int b){}
}
class BComponent:public Component{
public:
using Component::Component;
BComponent(int a, int b) : Component(int a, int b){}
}
Further, I have a Multi-Component (still generic here):
typedef shared_ptr<AComponent> AComponentPtr;
typedef shared_ptr<BComponent> BComponentPtr;
class MultiComponent{
public:
vector<AComponentPtr> A_components;
vector<BComponentPtr> B_components;
explicit MultiComponent(vector<AComponentPtr> As, vector<BComponentPtr> Bs){
this->A_components = As;
this->B_components = Bs;
}
}
Finally, I have a specific use case of this component hierarchy:
class WidgetComponentA:public AComponent{...}
class WidgetComponentB:public BComponent{...}
class Widget:public MultiComponent{
public:
using MultiComponent::MultiComponent;
Widget(WidgetComponentA a, WidgetComponentB b, WidgetComponentB c)
: MultiComponent(???){
}
}
Currently, I have the MultiComponent class constructor within Widget set up as follows:
class Widget:public MultiComponent{
public:
using MultiComponent::MultiComponent;
Widget(WidgetComponentA a, WidgetComponentB b, WidgetComponentB c)
: MultiComponent({(AComponentPtr)&a},{(BComponentPtr)&b, (BComponentPtr)&c}){}
}
Because this yields no errors on compilation.
Then, I construct the widget in my main method like so:
main(){
WidgetComponentA a = WidgetComponentA(1,2);
WidgetComponentB b = WidgetComponentB(3,4);
WidgetComponentB c = WidgetComponentB(5,6);
// now, the widget:
Widget widget = Widget(a,b,c);
// however, the pointers within the widget
// do not access valid addresses in memory.
return 0;}
The shared pointers within the Widget widget object do not reference any valid locations in memory, and fail with,
Attempt to take address of value not located in memory.
Ultimately, what I am trying to do is have Widget just hold on to the list of components of various derived types in the form of the base class shared pointers.
Then, I run generic, template functions on the class, and only cast the pointers to the widget-specific derived class pointers in functions specific to widgets.
I am using shared pointers to be safe, because I ran into the memory leak warnings...but if there is a simpler solution...

As I suggested in the comments, perhaps a polymorphic approach would be easier...
class MultiComponent{
public:
typedef std::vector<std::shared_ptr<Component>> components_vec;
components_vec components;
MultiComponent(components_vec& cv){
components = cv;
}
}
class Widget: public MultiComponent {
public:
Widget(MultiComponent::components_vec& cv)
: MultiComponent(cv){}
}
You can cast pointers to descendants of Component to Component*'s and then store them together.
Then, perhaps define a virtual void Component::display() = 0 to force the inheritors to define some sort of behaviour to your needs.

Perhaps I misunderstand what you ask but if you want to deal with objects of shared ownership then you have to make them such:
main()
{
auto a = std::make_shared<WidgetComponentA>(1,2);
auto b = std::make_shared<WidgetComponentB>(3,4);
auto c = std::make_shared<WidgetComponentB>(5,6);
// now, pass the shared stuff to widget:
Widget widget = Widget(a,b,c); // make sure that Widget has
// such constructor that accepts
// the shared pointers
return 0;
}

Related

C++: Iteratively call a member's object methods /// a table of objects

I have a bunch of object classes (A, B and C in this example) which I instantiate in my application. They all inherit one and a same interface, which I call Base. I want to interate over the objects and do a call on them.
Here are the classes and the base:
class Base
{
public:
virtual CResult init() noexcept;
};
class A : public Base
{
public:
...
};
class B : public Base
{
public:
...
};
class C : public Base
{
public:
...
};
I have then an instance of A, B and C in the application, together with its init() method:
class Application
{
public:
CResult init() noexcept;
private:
A a;
B b;
C c;
};
CResult Application::init()
{
/// iterate on a, b, c and call .init()
/// add code
}
Now, I want to call the init() methods of all my objects a, b and c iteratively.
That would mean I need to define a table with a, b and c "references" (I say references, but yes it is not possible to have, say, vector of object references). Then to iterate over the table and call each member's init() method.
What is the best OOP way to achieve this? Can anyone share sample code with the table and the iteration?
The easiest way is probably this:
Base *ptrs[] = {&a, &b, &c};
for (auto ptr : ptrs)
ptr->init();
If the variables had the same type, you could shorten this to for (auto ptr : {&a, &b, &c}). But since the types are different, you have to manually spell the pointer type when creating the array.
I have implemented it using a std::vector. The following private member in the Application class definition holds the list of components:
std::vector<Base *> m_components;
The initialization of the list is currently in the constructor:
Application::Application()
{
m_components.push_back(&a);
m_components.push_back(&b);
m_components.push_back(&c);
/// add additional components as needed
}
CResult Application::init()
{
// call all components' init
for(const auto& cmp: m_components)
{
CResult rc = cmp->init();
if(rc != CResult::OK)
{
// error; report, break the initalization
}
}
// initialization passed
}
The same approach can be used for deinit, start, stop, etc methods, and make the code quite readable and maintainable.

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;
}
};

Create derived class in base class based on parameter

My question is more or less identical to the one at Need a design pattern to remove enums and switch statement in object creation However I don't see that the abstract factory pattern suits well here.
I'm currently planning the refactoring/reimplementation of some existing DAL/ORM mixture library. Somewhere in the existing code there is code that looks like this:
class Base
{
static Base * create(struct Databasevalues dbValues)
{
switch(dbValues.ObjectType)
{
case typeA:
return new DerivedA(dbValues);
break;
case typeB:
return new DerivedB(dbValues);
break;
}
}
}
class DerivedA : public Base
{
// ...
}
class DerivedB : public Base
{
// ...
}
So the library responsible for database communication populates a struct with all information about the database entity and then the above create() method is called to actually create the corresponding object in the ORM.
But I don't like the idea of a base class knowing of all its derived classes and I don't like the switch statement either. I also would like to avoid creating another class just for the purpose of creating those Objects. What do you think about the current approach? How would you implement this functionality?
This has been discussed here milliions of times. If you don't want to create a separate factory class, you can do this.
class Base
{
public:
template <class T>
static void Register (TObjectType type)
{
_creators[type] = &creator<T>;
}
static Base* Create (TObjectType type)
{
std::map <TObjectType, Creator>::iterator C = _creators.find (type);
if (C != _creators.end())
return C->second ();
return 0;
}
private:
template <class T>
static Base* creator ()
{
return new T;
}
private:
typedef Base* (::*Creator) ();
static std::map <TObjectType, Creator> _creators;
};
int main ()
{
Base::Register <Derived1> (typeA);
Base::Register <Derived2> (typeB);
Base* a = Base::Create (typeA);
Base* b = Base::Create (typeB);
}
Let's say you replace the switch with a mapping, like map<ObjectType, function<Base* (DatabaseValues&)>>.
Now, the factory (which may or may not live in the base class), doesn't need to know about all the subclasses.
However, the map has to be populated somehow. This means either something populates it (so your knowing about all subclasses problem has just been pushed from one place to another), or you need subclasses to use static initialization to register their factory functions in the map.
No matter what you do, you'll need either switch-case or some other construct that will just hide similar logic.
What you can and should do, however, is remove the create method from your Base - you're totally correct it shouldn't be aware of it's derived ones. This logic belongs to another entity, such as factory or controller.
Just don't use enums. They are not OO construction, that was why JAVA did not have them at the beginning (unfortunately the pressure was too big to add them).
Consider instead of such enum:
enum Types {
typeA,
typeB
};
this construction, which do not need switch (another non OO construction in my opinion) and maps:
Types.h
class Base;
class BaseFactory {
public:
virtual Base* create() = 0;
};
class Types {
public:
// possible values
static Types typeA;
static Types typeB;
// just for comparison - if you do not need - do not write...
friend bool operator == (const Types & l, const Types & r)
{ return l.unique_id == r.unique_id; }
// and make any other properties in this enum equivalent - don't add them somewhere else
Base* create() { return baseFactory->create(); }
private:
Types(BaseFactory* baseFactory, unsigned unique_id);
BaseFactory* baseFactory;
unsigned unique_id; // don't ever write public getter for this member variable!!!
};
Types.cpp
#include "Types.h"
#include "Base.h"
#include "TypeA.h"
#include "TypeB.h"
namespace {
TypeAFactory typeAFactory;
TypeBFactory typeAFactory;
unsigned unique_id = 0;
}
Types Types::typeA(&typeAFactory, unique_id++);
Types Types::typeA(&typeBFactory, unique_id++);
So your example (if you really would need this function then):
class Base
{
static Base * create(struct Databasevalues dbValues)
{
return dbValues.ObjectType.create();
}
};
Missing parts should be easy to implement.

How to search through and assign from a collection of c++ derived objects?

I got a good answer to the technical part of my question as to why my current approach to this is not working (assigning derived** to base** is type-unsafe, see also Converting Derived** to Base** and Derived* to Base*). However, I still don't have a good idea of how to implement what I'm thinking of in a C++ manner. I'm starting a new question, since the last title was too specific.
Here's perhaps a clearer explanation of what I am trying to do:
Create a number of objects which are all instances of classes derived from one single class.
Store these objects in some type of master container along with a compile-time human-readable identifier (probably a string?).
Get a list of identifiers from other components, search through the master container, and pass them back (pointers/references to) the corresponding objects so they can read/modify them. I think I need to break type-safety at this point and assume that the components know the derived type that they are asking for by identifier.
I thought this would be relatively simple and elegant to do with maps, vectors, and pointers to objects (I give a simplified example in my my previous question), but it seems I'm going to have to be doing a lot of C-style type casting to allow the components to pass pointers to the locations to store the value from the master container. This indicates to me that I'm not following a C++ paradigm, but what "should" I do?
[Edit] Here's some hypothetical sample code for how I envisioned this, hope this clarifies my thinking:
#include <map>
#include <vector>
#include <string>
using namespace std;
class BaseObj {};
class Der1Obj: public BaseObj {};
class Der2Obj: public BaseObj {};
typedef map<string, BaseObj**> ObjPtrDict;
typedef map<string, BaseObj*> ObjDict;
class BaseComp
{
public:
ObjPtrDict objs;
};
class DervComp
{
DervComp(){objs["d1"] = &d1; objs["d2"] = &d2; } // This wouldn't compile
Der1Obj* d1;
Der2Obj* d2;
}
typedef vector<BaseComp*> CompList;
void assign_objs(CompList comps, ObjDict objs)
{
for (auto c = comps.begin(); c != comps.end(); c++)
for (auto o = c.objs.begin(); o != c.objs.end(); o++)
*(o->second) = objs[o->first];
}
int main(int argc, char* argv[])
{
Der1Obj d, d1;
Der2Obj d2;
ObjDict objs;
objs["d"] = &d;
objs["d1"] = &d1;
objs["d2"] = &d2;
DervComp c;
vector<DervComp*> comps;
comps.push_back(&c);
assign_objs(comps, objs);
return 0;
}
If I got what you want right, you can do it like this:
#include <vector>
class Base
{
public:
enum eDerived
{
//name these whatever you like
DER1,//for first derived class
DER2,//for second derived class
DER3//for third derived class
};
virtual eDerived type() = 0;//this will return the class type.
};
class Derived1: public Base
{
public:
virtual eDerived type() { return DER1; }
};
class Derived2: public Base
{
public:
virtual eDerived type() { return DER2; }
};
class Derived3: public Base
{
public:
virtual eDerived type() { return DER3; }
};
int main()
{
std::vector<Base*> myList;//container for all elements
//You can store a pointer to any of the derived classes here like this:
Base * a = new Derived1();
Base * b = new Derived2();
Base * c = new Derived3();
myList.push_back(a);
myList.push_back(b);
myList.push_back(c);
//Iterating through the container
for( Base * tmp: myList)
{
//You can check the type of the item like this:
if( tmp->type() == Base::DER1 )
{
//and cast to a corresponding type.
//In this case you are sure that you are casting to the right type, since
//you've already checked it.
Derived1 * pointerToDerived1 = static_cast<Derived1 *>(tmp);
}
}
}
Ofc you can choose any type of container. If you want to give them an ID, you could either use map, or add it into the class itself.
I read your other post, but I think I donĀ“t understand why you would use double pointers. In my understanding you would just use a normal pointer.
E.g.
class Base
{
};
class Deriv : public Base
{
};
std::map< std::string, Base* > ObjectStore;
function Component1( ... )
{
Base* b = ObjectStore[ "MyObject" ];
b->DoSomeFancyStuff();
}
function ModifyObjectStore( )
{
delete ObjectStore[ "MyObject" ];
ObjectStore[ "MyObject" ] = new Derived();
}
I hope this helps.
You says, "pass them back the corresponding object". For this why do you want to pass back the base**? You can simply give back the a map from string to pointer back. Please see the code below for explanation.
class Container
{
void add(const string& aKey_in, Base* b)
{
myObjects[aKey_in] = b;
}
void getObjs(list<string> aKeys_in, map<string,Base*>& anObjMap_out)
{
for(all string s in the aKeys_in)
anObjMap_out[s] = myObjects[s];
}
private:
map<string, base*> myObjects;
};
You conditions meet here:
Create a number of objects which are all instances of classes derived from one single class.
You could extend the class to have creation logic, factory logic etc.
Store these objects in some type of master container along with a compile-time human-readable identifier (probably a string?).
Achieved with the map
Get a list of identifiers from other components, search through the master container, and pass them back (pointers/references to) the corresponding objects so they can read/modify them. I think I need to break type-safety at this point and assume that the components know the derived type that they are asking for by identifier.
You don't need to pass back the pointer to pointer to the client. Just pass back the object pointers.
Additional note:
You could implement the pointers with shared_ptr instead of raw pointers.
If your client code (whoever is using the getObjs() method) is written properly then you won't need a dynamic cast from base pointer to derived pointer. They should be able to work with the base pointer.
Anyway, that is a different question which you haven't asked yet.

One pointer, two different classes in c++

Suppose I have two structures a and b, each hold several variable in them (most of the variable are c++ core types but not all).
Is there a way to create a a pointer named c that can point to either one of them? Alternatively, is there a way to create a set that can hold either one of them?
Thanks
The usual way to create a pointer that can point to either of the two is to make them inherit from a common base-class. Any pointer of the base-class can point to any sub-class. Note that this way you can only access elements that are part of the base-class through that pointer:
class Base {
public:
int a;
};
class Sub1 : public Base {
public:
int b;
};
class Sub2 : public Base {
public:
int c;
};
int main() {
Base* p = new Sub1;
p.a = 1; // legal
p.b = 1; // illegal, cannot access members of sub-class
p = new Sub2; // can point to any subclass
}
What you are trying to achieve is called polymorphism, and it is one of the fundamental concepts of object oriented programming. One way to access member of the subclass is to downcast the pointer. When you do this, you have to make sure that you cast it to the correct type:
static_cast<Sub1*>(p).b = 1; // legal, p actually points to a Sub1
static_cast<Sub2*>(p).c = 1; // illegal, p actually points to a Sub1
As for your second question, using the technique described above, you can create a set of pointers to a base-class which can then hold instance of any of the subclasses (these can also be mixed):
std::set<Base*> base_set;
base_set.insert(new Sub1);
base_set.insert(new Sub2);
Alternatively, is there a way to create a set that can hold either one
of them?
Take a look at Boost.Any and Boost.Variant. If you have just 2 classes, then variant should suffice. If you plan other types, and don't want to recompile this 'set', then use any.
Then use any container of either any or variant.
#include <boost/any.hpp>
#include <boost/variant.hpp>
#include <vector>
class A { };
class B { };
class C { };
int main()
{
// any
std::vector<boost::any> anies;
anies.push_back(A());
anies.push_back(B());
A a0 = boost::any_cast<A>(anies[0]);
A b0 = boost::any_cast<A>(anies[1]); // throws boost::bad_any_cast
// variant
std::vector<boost::variant<A,B> > vars;
vars.push_back(A());
vars.push_back(B());
A a1 = boost::get<A>(vars[0]);
A b1 = boost::get<A>(vars[1]); // throws boost::bad_get
// and here is the main difference:
anies.push_back(C()); // OK
vars.push_back(C()); // compile error
}
Edit: having more than 2 classes is of course possible for variant, too. But extending variant so it is able to hold a new unanticipated type without recompilation is not.
If a and b are unrelated, then you can use a void* or, better, a boost any type.
If a is superclass of b, you can use an a* instead.
If they both inherit from the same type you can do it. Thats how OOP frameworks work, having all classes inherit from Object.
Although you can do that, what would that pointer mean? If any portion of your application gets hold on the pointer to 'either a or b', it cannot do a lot with it, unless you provide extra type information.
Providing extra type information will result in client code like
if( p->type == 'a' ) {
... a-specific stuff
} else if( p->type == 'b' ) {
... b-specific stuff
} ...
Which isn't very useful.
It would be better to delegate 'type-specificness' to the object itself, which is the nature of object-oriented design, and C++ has a very good type-system for that.
class Interface {
public:
virtual void doClientStuff() = 0; //
virtual ~theInterface(){};
};
class A : public Interface {
virtual void doClientStuff(){ ... a-specific stuff }
};
class B : public Interface {
virtual void doClientStuff(){ ... b-specific stuff }
};
And then your client code will become more type-unaware, since the type-switching is done by C++ for you.
void clientCode( Interface* anObject ) {
anObject->doClientStuff();
}
Interface* i = new A();
Interface* j = new B();
clientCode( i );
clientCOde( j );
There are several ways to do this:
Using the more generic base type, if there is an inheritance relationship.
Using void* and explicitly casting where appropriate.
Creating a wrapper class with the inheritance relationship needed for #1.
Using a discriminating container via union.
Since others have already described the first three options, I will describe the fourth. Basically, a discriminated container uses a union type to use the storage of a single object for storing one of multiple different values. Typically such a union is stored in a struct along with an enum or integral type for distinguishing which value is currently held in the union type. As an example:
// Declarations ...
class FirstType;
class SecondType;
union PointerToFirstOrSecond {
FirstType* firstptr;
SecondType* secondptr;
};
enum FIRST_OR_SECOND_TYPE {
FIRST_TYPE,
SECOND_TYPE
};
struct PointerToFirstOrSecondContainer {
PointerToFirstOrSecond pointer;
FIRST_OR_SECOND_TYPE which;
};
// Example usage...
void OperateOnPointer(PointerToFirstOrSecondContainer container) {
if (container.which == FIRST_TYPE) {
DoSomethingWith(container.pointer.firstptr);
} else {
DoSomethingElseWith(container.pointer.secondptr);
}
}
Note that in the code below, "firstptr" and "secondptr" are actually two different views of the same variable (i.e. the same memory location), because unions share space for their content.
Note that even though this is a possible solution, I seriously wouldn't recommend it. This kind of thing isn't very maintainable. I strongly recommend using inheritance for this if at all possible.
Just define a common superclass C and two subclasses A, B of C. If A and B have no common structure (no common attributes), you can leave C empty.
The define:
A *a = new A();
B *b = new B();
C *c;
Then you can do both
c = a;
or
c = b;
Abstract Class !!!! -- simple solutions
To have a base class that can be used as a pointer to several derived sub classes. (no casting needed)
Abstract class is define when you utilize a virtual method in it. Then you implement this method in the sub-class... simple:
// abstract base class
#include <iostream>
using namespace std;
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area (void) =0;
};
class Rectangle: public Polygon {
public:
int area (void)
{ return (width * height); }
};
class Triangle: public Polygon {
public:
int area (void)
{ return (width * height / 2); }
};
int main () {
Polygon * ppoly1 = new Rectangle (4,5);
Polygon * ppoly2 = new Triangle (4,5);
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
cout << ppoly1->area() << '\n';
cout << ppoly2->area() << '\n';
return 0;
}