I want to instantiate a base class pointer to point to a newly constructed derived class object. The actual class for the object will change depending on the application type, so I want to use a Factory method to switch on certain variables in order to construct the right object.
However I don't want to have to do the switch each time. In fact, once the application starts, the type of object I want to create in this situation will always be the same - so actually I only need to do this switch only once.
Can I pass in a derived class Constructor to the function creating the object?
For example:
typedef DerivedObject (*DerivedClassConstructor)( void );
class ContainingClass:
{
public:
ContainingClass ( DerivedClassConstructor * f )
{
baseptr = f();
}
BaseClass * baseptr
};
Is there a better design?
Would it not be easier to templatise the code.
That way it looks like normal code.
class BaseClass
{};
class Derived: public BaseClass
{};
template<typename T>
class ContainingClass
{
public:
ContainingClass()
{
baseptr = new T();
}
BaseClass * baseptr;
};
int main()
{
ContainingClass<Derived> cont;
}
I think that's pretty sane. Just pass a function object and save it since it seems you need to recall it later (otherwise why not pass the pointer directly and create the object before?)
class ContainingClass:
{
public:
typedef boost::function<BaseClass*()> factory_fn;
public:
ContainingClass (factory_fn f )
:m_f(f)
{
baseptr = m_f();
}
BaseClass * baseptr
factory_fn m_f;
};
template<typename T>
struct DerivedFactory {
BaseClass *operator()() {
return new T;
}
};
ContainingClass c((DerivedFactory<DerivedClass>()));
You can't do it with a constructor, since a constructor is not actually returning a class instance.
You talk about a factory method, and you got half way towards actually using one. However, it is not a good idea to create a dependency from base class to derived class - why can't your factory method simply return (a pointer to) BaseClass objects?
typedef BaseClass* (*BaseClassFactory)( void );
Related
I want to make a base class which handles the construction of sub-classes. A sub-class then wants to call a function from the base class so I am passing it a pointer to be able to achieve this. The base class then passes back the sub-class to the user.
Is the below method an acceptable strategy for this? And is it safe to pass back an object in this fashion? If not, what would be a better alternative? I am concerned this becomes messy quickly as each subclass needs to be a friend for the base and it generally seems a bit clunky.
class SubClass
{
private:
SubClass(MyClass* parent) {
...
parent->DoStuff();
...
}
}
class MyClass
{
public:
SubClass CreateSubClass() {
return SubClass(this);
}
private:
void DoStuff() {
...
}
friend class SubClass;
}
MyClass a;
SubClass b = a.CreateSubClass();
Thanks in advance!
Nothing is really wrong with your code pattern. As super already mentioned in a comment, I'd probably pass a MyClass& reference instead of a MyClass* pointer.
If you want to reduce the class interdependencies and remove the need for friendship, you might pass a functor instead of the MyClass:
class SubClass
{
public:
template <class F>
explicit SubClass(F stuff_doer) {
...
stuff_doer();
...
}
};
class MyClass
{
public:
SubClass CreateSubClass() {
return SubClass([this] { DoStuff(); });
}
private:
void DoStuff();
};
Or if you don't want or can't have the SubClass constructor defined in a header file, instead of a constructor template you could use a std::function functor to erase the functor type:
class SubClass
{
public:
explicit SubClass(std::function<void()> stuff_doer);
};
Edit: My question might just be asking how to downcast a unique_ptr<base> to unique_ptr<derived> (which is already answered), but I am not 100% sure what I am asking
I have an Abstract Base Class Base
class Base{
public:
Base();
struct pStruct{};
virtual pStruct pFunc(std::vector<double> data) = 0;
protected:
CustomType dataValue;
};
and two derived classes Derived1 and Derived2 that implement Base
class Derived1 : public Base {
public:
struct pStructD1 : Base::pStruct {
CustomType data1;
std::vector<double> data2;
};
Derived1(uint32_t foo1, std::vector<double> foo2, ...);
virtual pStruct pFunc(std::vector<double> data) override;
private:
uint32_t bar1{0};
};
class Derived2 : public Base {
public:
struct pStructD2 : Base::pStruct {
int32_t data3;
std::vector<double> data4;
double data5
};
Derived2(std::vector<double> foo1, std::vector<double> foo2, ...);
virtual pStruct pFunc(std::vector<double> data) override;
private:
std::vector<double> bar2;
};
When calling class method pFunc(std::vector<double> data), each derived class will return different types, and amounts of values. I tried making this work with a covariant return type, so Derived1::predict(data).key1 might be a matrix, and .key2 might be something else, and so on. Derived2::predict(data).key1 might be the only key, and it could be a boolean. Each derived class defines their own ::predict() return fields, because they vary significantly.
The issue is, I construct these derived classes with a factory, that reads some of the input (construction is via ifstream), and figures out what derived class it should be, and then calls the corresponding factory.
class BaseFactory {
public:
static std::unique_ptr<Base> createObj(std::ifstream & file){
file.read((char *) specificTypeString, 2);//This isn't actually the code, just assume this part works
if(specificTypeString == "D2"){
return D2BaseFactory::createObj(file);
}
else if(specificTypeString == "D1"){
return D1BaseFactory::createObj(file);
}
else{
throw std::runtime_error("error");
}
}
};
With std::unique_ptr<Base> D1BaseFactory::createObj(std::ifstream & file); returning std::unique_ptr<Derived1>(new Derived1(param1, param2, ...)); and the same thing for `D2BaseFactory'.
Problem is, if I construct a Derived class with the common BaseFactory, and call pFunc() on the returned unique_ptr, it always will be the empty Base::pStruct == {} and thus trying to access members of the covariant pStructs isn't possible. I know this is because the factory createObj returns the base type, but is there any way to dynamically return the type I want so I can access the necessary fields in the derived pStructs? I think using raw pointers might work, but if possible i'd like to keep them as unique pointers.
You can do something similar to this:
class Base
{
public:
...
std::unique<pStruct> pFunc(...) { return DopFunc(); }
protected:
virtual std::unique<pStruct> DopFunc() = 0;
};
class Derived1 : public Base
{
public:
struct pStructD1 : Base::pStruct { ... };
// Used when calling the child factory directly...
std::unique_ptr<pStructD1> pFunc(...)
{
return std::make_unique<pStructD1>(...);
}
protected:
// Used when called through the Base factory...
std::unique<pStruct> DopFunc(...) override
{
// Call the other function for code sharing... (DRY)
return pFunc(...);
}
....
};
This could make sense if you used the derived class when you need the derived objects.
The real question is why you need to used the derived types... If it is for initialisation purpose, then maybe the factory should do it before returning the value.
If it is for some processing, then maybe you should have some virtual functions in pStruct. That way, you never need to know the derived type returned by the factory.
In some case, the visitor pattern might also be a solution.
If you need to always use the specific struct, then why not always use the specific factory too?
You can also cast the result but if you need to do it every time you create an object, it might make the code more complex that it need to be.
Alternatively, you could also have a template member function let say template <class T> std::unique_ptr<T> pFuncT(...) { ... }. That way, the client code can specified the desired type directly at construction. An empty object or an exception could be throw if the type is incorrect.
Suppose we have an Abstract class and child (derived from abstract) classes. I know we can instantiate from derivedClass like this:
AbstractBase *foo = new DerivedClass1();
But, is this the right way to define the top line code:
AbstractBase foo = *(new DerivedClass1());
I don't want to declare the Abstract class via pointer. But, What is the best way to do this and manage the memeory leak?
Thanks a lot
AbstractBase foo = *(new DerivedClass1()); will try to construct an instance of AbstractBase (which you can't do, it's abstract) using a constructor which takes an object of type DerivedClass1 (or something it's convertible to.
If you don't want to end up with a pointer to AbstractBase, but you do want to use new to allocate the object dynamically, then you probably want:
AbstractBase& foo = *(new DerivedClass1());
to define a reference to AbstractBase from your new DerivedClass1
Here is a very simple example of how to "chain" copy constructors. Note that the syntax may be a bit off, but this is the general idea:
class ABase {
public:
ABase(const ABase& ab) {
basevar = ab.getBasevar();
}
int getBasevar() { return basevar; }
private:
int basevar;
};
class c1 : public ABase {
public:
c1(const c1& c) : ABase(c) {
cvar = c.getCvar();
}
private:
int cvar;
};
In particular, note the use of the : operator between the function declaration and definition; this space allows for multiple direct assignments in a constructor function (possibly in other functions as well) and its content is called an "initialization list". Note also this answer which details some more examples.
I have a base class called Base which defines a virtual function. The class Derived now inherits from it and implements/overwrites that virtual function. The following code works just fine:
Base* pB = new Derived();
pB->virtual_function(); // function of class Derived gets called -> good
My problem is, that I now store all my derived instances in a STL container std::map<ID, Base*>. This seems to cause problems, because when I later iterate over that container and try for each Base* to call my virtual function, the runtime only recognizes the pointers as type Base* and does not call the overridden implementation in the class Derived.
Is there a way to get that working as intended or am I missing a crucial point here?
EDIT 1: Some additional code was requested, so here we go:
std::map<ComponentType, Base*> m_Components;
// The factory instantiates a Derived* (via functors) and returns it as Base*
Base* pB = m_pComponentFactory->createComponent(this, type);
// Lazy insert (since there is no map entry with key 'type' at that stage)
m_Components[type] = pB;
[...]
Base* pB;
for(ComponentMap::const_iterator it = m_Components.begin(); it != m_Components.end( ); ++it)
{
pB = it->second;
pB->virtual_function(); // goes to Base instead of Derived
}
EDIT 2: One thing I just realized is that I do not call dynamic_cast (or something similar) after creating the Derived instance via the functor (but I wouldn't know what to cast it to anyway since it is all generic/dynamic). It is just a return creator() with creator being the functor. Is that the issue?
Definition of creator type (the functon type):
typedef Base*(*ComponentCreator)([some params]);
Edit 3:
The actual functor is for example defined like this (Renderable and Location being derived classes from Base):
&Renderable::Create<Renderable> // or
&Location::Create<Location>
with the Create() method being a template function in the class Base.
template<typename T>
static Component* Create([some params])
{
return new T([some params]);
}
EDIT 4:
The problems seems to be my clone() + CopyConstructor handling. My clone currently looks like this:
Base* Base::clone() const
{
return new Base(*this);
}
Since I only create a Base*, the virtual resolution later on cannot work. The problem I am now left with though, is that I a missing an idea how to change the cloning. As shown in EDIT 1 I have my m_Components map with Base* pointers. I now need to clone them but I only know that they are of Base* and not of which exact derivative. One idea that comes to mind, might be to store functor used to create the Derived instance in the first place in the class, to reuse it later. So my clone would look something like this:
Base* Component::clone() const
{
return m_pCreationFunctor([some params]);
}
Anyone seeing a better approach?
You are a victim of slicing. When you copy construct a Base, you will lose the Derived parts of the object. See http://en.wikipedia.org/wiki/Object_slicing for a bit more detail. If the base class is not supposed to be instantiated, you might consider making it abstract to prevent making this mistake in future.
The fix in this case is probably to have a virtual Base * clone() method and override it in derived classes.
i.e.
class Base{
...
virtual Base * clone() const = 0;
...
};
class Derived : public Base {
...
Base * clone() const override { return new Derived(*this); }
...
};
If you really want to avoid rewriting the clone method, you could use an intermediate CRTP class i.e
struct Base{
virtual Base * clone() = 0;
};
template <typename D>
struct B : public Base {
virtual Base * clone() { return new D(*static_cast<D*>(this)); }
};
struct D : public B<D>{};
I want to use mock object to test my class which uses shared_ptr pointer.
It likes ,
struct MyInterface {
// public functions
};
class MyClass {
public:
MyClass (shared_ptr<MyInterface> handle) : m_handle(handle) {}
~MyClass() {}
// ...
private :
shared_ptr<MyInterface> m_handle;
}
When I test MyClass, I pass a mock object to it.
struct NullDeleter {template<typename T> void operator()(T*) {} };
TMockObject<MyInterface> * mock = new TMockObject<MyInterface>();
shared_ptr<MyInterface> handle((MyInterface*)(*mock), NullDeleter());
MyClass myClass(handle);
delete mock;
the question is I have to use a NullDeleter when i create the shared pointer, otherwise, mock will be delete as a MyInterface which cause error.
Is there any better design for this ?
thanks~
If I could understand what you want to do and I do not take the mistake,
I prefer to have method inside myClass class to check proper value of argument.
It means, you should after pass your argument to class constructor, provide another method to check the value.
Add a virtual destructor to MyInterface, and then when you delete an (abstract) MyInterface, all the sub class destructor is invoked as well.
struct MyInterface {
virtual ~MyInterface() { }
// public functions
};