Saving abstract value object in wrapper and Usage of inheritance - c++

I have issues regarding C++ class inheritance.
I have a class which has virtual method, for example:
class IFoo {
public:
virtual int sayFoo() = 0;
};
And I have several implementations, for example:
class Foo1: public IFoo {
public:
virtual int sayFoo() {
return 1;
}
};
class Foo2: public IFoo {
public:
virtual int sayFoo() {
return 2;
}
};
I want to hold IFoo instance inside a dummy container class (like a sort of wrapper) exposing the same interface of IFoo:
class DummyWrapper : public IFoo {
public:
DummyWrapper(IFoo& foo): foo{foo} {}
virtual int sayFoo() {
return foo.sayFoo(); //ALPHA
}
private:
IFoo& foo; //BETA
};
Normally everything should work, for example, like this:
IFoo& foo = Foo1{};
DummyWrapper wrapper{foo};
wrapper.sayFoo();
My problem is that foo is actually just a r-value that is removed after its scope goes out, like here:
DummyWrapper generateWrapper() {
return DummyWrapper{Foo1{}};
}
This lead to read problems in "ALPHA" line.
A solution would be to put the r-value on the heap and use pointers to access the foo. Since I'm new to C++ and maybe I'm falling into a XY problem, my question is:
is this the only solution? Isn't there a better method to use to solve the issue?
I don't think i can replace "BETA" line with IFoo foo since in this way the DummyWrapper will always store the bytes of a IFoo, not of a IFoo implementation. Or maybe I can use the value IFoo foo to call derived virtual methods?
Thanks for any kind reply

is this the only solution? Isn't there a better method to use to solve the issue?
As soon as polymorphism is involved, unfortunately, yes, it is and no, there isn't. But you get an almost equivalent solution to storing IFoo foo, if you use a smart pointer:
// member:
std::unique_ptr<IFoo> foo;
// constructor:
DummyWrapper(std::unique_ptr<IFoo>&& foo): foo(std::move(foo)) { }
// need to accept r-value ^
// reference: std::unique_ptr is only movable, not copiable!
// for the same reason, you need to preserve the r-value reference
// on assignment to member...
// creation of the wrapper:
return DummyWrapper(std::make_unique<Foo1>(/* arguments for constructor, if there are */));
I don't think i can replace "BETA" line with IFoo foo since in this way the DummyWrapper will always store the bytes of a IFoo, not of a IFoo implementation. Or maybe I can use the value IFoo foo to call derived virtual methods?
Absolutely correct: That's an effect called 'object slicing', at the point you assign a derived object to a base one, all the surplus stuff coming from the derived type gets lost. Pretty common problem (e. g. when people try to store derived objects in a std::vector<Base>).

Usually we create wrapper when we wants to alter the interface of a class or want to implement additional functionalities, for example
std::queue<T> is wrapper/adapter on std::std::deque<T>(by default)
The std::queue<T> class template acts as a wrapper to the underlying container - only a specific set of functions is provided. The queue pushes the elements on the back of the underlying container and pops them from the front.
In your case i don't think you need DummyWrapper you can use IFoo in place of DummyWrapper and it will do the same job.
Let consider following function,
bool isEven( IFoo& ifoo) // Not const& because sayFoo() is not const method.
{
return ( 0 == ( ifoo.sayFoo() % 2)) ;
}
This function will work for all types like Foo1 , Foo2, and no wrapper is required.

Related

Access derived class's method covariant return, with derived constructed from factory with unique_ptr<AbstractBase>

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.

Member of derived by pointer to base, static_cast, crtp, removing templates

Looking for: accessing member of a derived class from a pointer to base.
Reductio ad absurdum:
class Base
{
public:
int member_of_base;
};
class Derived : public Base
{
public:
int member_of_derived;
};
I'm currently using templates:
template <class T>
class Client
{
T* data; // T is Base or Derived
};
There are few levels of composition in the class hierarchy, so I have to carry the template type parameter through all of the hierarchy. What is the best approach to overcome this?
Obviously I cannot access the member of Derived via a pointer to Base, i.e:
Base* foo = new Derived();
foo->member_of_derived; // no go
Thus, I'm using:
Client<Base>
Client<Derived>
I'm trying to come up with a solution that works without the templates. Options that I know would work:
void* //plain old C and casting as necessary, they're all pointers
(as in memory addresses) in the machine
static_cast<Derived*>(pointer_to_base); //type safe at compile time.
wrapping the cast in a Client's template method (not to be confused with a design pattern here)
The last option seems to be the most "elegant", i.e:
template <class T>
T* get_data() const { return static_cast<T*>(data); }
However, looking here and there tells me there might exist a way unknown to me.
I saw CRTP, but that brings me back to templates, which is the original thing I want to go without.
What are the ways, or popular approaches, to achieve such a goal?
The real code uses shared_ptr, weak_ptr and enable_shared_from_this with weak_from_this. I'm looking for a type safe "polymorphic member" access.
EDIT: they're not just "ints". They can be totally different types, as in protobuf in base and Json::Value in derived. And I'm trying to use the pointers to Base/Derived, which in turn would give me access to their respective members.
A virtual getter can solve the issue for you; as data types differ, you might pack them into a std::variant.
class Base
{
// having private members probably is more appropriate
int member_of_base;
public:
using Data = std::variant<int, double>;
virtual ~Base() { } // virtual functions -> have a virtual destructor!
virtual Data getMember() // or just "member", if you prefer without prefix
{
return member_of_base;
}
};
class Derived : public Base
{
double member_of_derived;
public:
Data getMember() override
{
return member_of_derived;
}
};
std::unique_ptr<Base> foo = new Base();
foo->getMember(); // member_of_base;
std::unique_ptr<Base> bar = new Derived();
bar->getMember(); // member_of_derived;
Admitted, not yet totally without templates, std::variant is one, but I suppose in that form it is acceptable...
There are some issues with, though:
Accessing the value is not the simplest, you might consider visit function for.
More severe: Base class (or wherever else you define the variant to be used) needs to be aware of all types that might be in use, adding a new type will force to recompile all other classes.
It has the smell of bad design. Why should it be necessary for a derived class to return something different than the base that shall serve the same purpose, though???
If you can delegate the work to be done to the classes themselves, you get around all these problems:
class Base
{
int member_of_base;
public:
virtual ~Base() { }
virtual void doSomething()
{
/* use member_of_base */
}
};
class Derived : public Base
{
double member_of_derived;
public:
void doSomething() override
{
/* use member_of_derived */
}
};
The latter would be the true polymorphic approach and normally the way to go; whereas the sample above returns void, you might just do all the calculations necessary in base and derived classes until you finally get to some common data type and return this one. Example:
class Base
{
int64_t m_balance; // in 100th of currency in use
public:
virtual ~Base() { }
virtual int64_t balance()
{
return m_balance;
}
};
class Derived : public Base
{
long double m_balance; // arbitrary values in whole currency entities
public:
int64_t balance() override
{
// calculate 100th of currency, correctly rounded:
return std::llround(m_balance * 100);
}
};
Admitted, I doubt pretty much representing a balance in double (even if long) is a good idea (issues with rounding, precision, etc)...

C++: Override method which has the same name as the class

Let's say I have a nice looking base class called base:
class base
{
public:
virtual void foo() const = 0;
};
Now, I have a class named foo that I would like to inherit from base and override base::foo:
class foo : public base
{
public:
virtual void foo() const override;
};
This is illegal in C++, as you are not allowed to name a method the same thing as the class (C++ greedily believes methods with the same name as the class are constructors, which are not allowed to have return types). Is there any way around this that doesn't involve changing the name of the class or method? I want external users to be able to create foo classes without the knowledge that there is a method base::foo called by someone else (imagine foo can be both a noun and a verb).
Is there any way around this that doesn't involve changing the name of the class or method?
No, there isn't.
All methods named foo are special in class foo -- they are constructors. Hence, they cannot be overridden virtual member functions.
I'll take a wild guess and just say NO.
You can have a lot of ambiguities in C++ (that sometimes have to be explicitly disambiguated), but I don't even see a way how a compiler or programmer could disambiguate this situation. Well, A programmer can (a function with a return type is obviously not a constructor), but C++ can't.
In C++, the only method that can have the class' name is its constructor.
So, no. You can't.
Okay, here's my (slightly evil) solution...
// Create an intermediate class which actually implements the foo method:
class foo_intermediate : public base
{
public:
virtual void foo() const override;
};
// Derive from that class and forward the constructor along
class foo : public foo_intermediate
{
public:
using foo_intermediate::foo_intermediate;
private:
friend class foo_intermediate;
// Actual implementation for the foo function goes here
void foo_impl() const;
};
// In some CPP file:
void foo_intermediate::foo() const
{
// Need to access the typename foo via namespace (global here)
static_cast<const ::foo*>(this)->foo_impl();
}
Actually calling foo is a bit funny, since this can't work:
void bar()
{
foo x;
x.foo(); // <- illegal attempt to access to the foo constructor
}
You must access through an alias:
void baz()
{
foo x;
base& rx = x;
rx.foo(); // legal
}
As an alternative, you can use a typedef:
class foo_impl : public base
{
public:
virtual void foo() const override;
};
using foo = foo_impl;
This gets around the issue of calling x.foo(), since it no longer appears as a constructor access.
I made a Gist so others could play with the two solutions if they are so inclined.

Alternative to casting return pointer of base class protected method?

I came up with a class that uses a protected nested struct, intending for derived classes to augment the struct. To that end, I declared a virtual method for allocating the struct.
Now, the base class does some not-trivial amount of work in processSomeData and I would like the derived class to reuse it.
Which leads to the following:
class A
{
public:
virtual void doProcessing(); // uses processSomeData()
protected:
struct someData
{
virtual ~someData() {};
// data members
};
virtual someData* processSomeData(); // uses allocateSomeData()
virtual someData* allocateSomeData();
};
class B : public A
{
public:
virtual void doProcessing()
{
derivedData* myData =
static_cast<derivedData*>(A::processSomeData()); // *** seems a little suspect
// do work on the additional data members in myData
}
protected:
struct derivedData : public someData
{
// more data members
};
virtual derivedData* allocateSomeData();
};
Because allocateSomeData is overridden, I know A::processSomeData is returning a someData* pointing to a derivedData, so static_cast is definitely safe.
That said, it feels a little off that I should have to cast from a base to derived at all, when everything else seems pretty kosher.
Is there a better/proper way to do this, without using a cast? Or do I have to re-design my classes/structs?
It is because the compiler doesn't know for sure that processSomeData uses allocateSomeData to create the someData struct. So far as the compiler knows the someData, that is returned from processSomeData might well be just an instance of someData. derivedData is someData but not the other way round.
While the template argument is a good method, let me put a vote in for another solution.
First we move processSomeData into the nested someData struct, keeping it virtual. Its implementation does all the work common to someData and its derived classes. We also have a new protected virtual function, call it furtherProcess. For someData it is empty. For every derived class, it handles whatever is needed. The last line of someData::processSomeData() is furtherProcess().
This use of a hook function at the end avoids the Call Super code smell implicit in the original set-up, which is often seen with these downcasts.
I resolved the issue by moving the nested class out and making it a template argument, because I would never use someData and derivedData concurrently.
struct someData
{
virtual ~someData() {};
// data members
};
template <typename DataType = someData>
class A
{
public:
virtual void doProcessing(); // uses processSomeData()
protected:
typedef DataType myDataType;
virtual myDataType* processSomeData(); // uses allocateSomeData()
virtual myDataType* allocateSomeData();
};
struct derivedData : public someData
{
// more data members
};
class B : public A<derivedData>
{
public:
virtual void doProcessing()
{
myDataType* myData = A::processSomeData();
// do work on the additional data members in myData
}
protected:
virtual myDataType* allocateSomeData();
};
While the nested class looked like a good way to encapsulate information, it did not seem to be worth the trade-off between type-safety and performance.
This answer, discovered shortly after I made the change, seems to somewhat vindicate the decision.

C++ polymophism issue, Instantiating from child class; NOT to declare abstract class as pointer

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.