Changing an object from one derived class to another - c++

I have a couple of classes that share a common base class, with the exception that they differ in the way their methods work. So in the example below, Adder and Multiplier are the same except for the way in which their calculation is performed.
Is there a way to change "a" to a Multiplier on the fly? Do I need to implement methods which convert derived classes to each other? e.g. something like
a = a.asMultiplier()?
As you can see in the code below I tried reinterpret_cast to a Multiplier, with no luck, it still acts like an Adder. (gcc OS X v4.2.1)
#include <iostream>
class Base {
protected:
int a,b;
public:
Base(int a, int b) {
this->a = a;
this->b = b;
}
virtual ~Base() { }
virtual int calculate() = 0;
};
class Adder : public Base {
public:
Adder(int a, int b) : Base(a, b) {
}
int calculate() {
return this->a + this->b;
}
};
class Multiplier : public Base {
public:
Multiplier(int a, int b) : Base(a, b) {
}
int calculate() {
return this->a * this->b;
}
};
int main() {
Base* a = new Adder(3,4);
Base* m = new Multiplier(3,4);
std::cout << "Adder gives " << a->calculate() << std::endl;
std::cout << "Multiplier gives " << m->calculate() << std::endl;
a = reinterpret_cast<Multiplier*>(a);
std::cout << "Now adder gives " << a->calculate() << std::endl;
delete a;
delete m;
return 0;
}

The best thing that comes up to me to solve this, is implementing a copy constructor, taking the base class:
class Multiplier : public Base {
public:
Multiplier(int a, int b) : Base(a, b) {
}
explicit Multiplier(const Base& iBase) : Base(iBase.a, iBase.b) {
}
int calculate() {
return this->a * this->b;
}
};
But since I am not the most advanced c++ developer here, it might not be correct or other people might have a better idea, just trying :)

I would propose to decouple the object's data from its operations. This way you can easily construct one object from another, overtaking the data. So your "conversion" will look like this: Multiplier m = new Multiplier(a);
Doing it the way you are asking for is impossible in C++.

This seems to me that you would need utility classes that operate on data: Change your base class to a Data class whose purpose is only to store the data and pass the data explicitly to the Adder, Multiplier etc. classes.
You can still use inheritance in the utility classes if it makes sense after the above refactoring: in this case base would also operate on a Data object, instead of being the Data itself

It is probably a good idea to change your design. In general I would say that it is a good idea to used inheritance when there is some kind of commonality shared by base and derived classes, not only in terms of data, but in terms of behaviour. Whilst not being very helpful advice directly I would suggest maybe reading some books on object oriented design principles. Trying to cast types in the way you are really makes no sense.

Related

is there a "semi-pure" virtual function in c++?

Is there a way to write an abstract base class that looks like it's forcing an implementer to choose among a myriad of pure virtual functions?
The abstract base classes I'm writing define a mathematically tedious function, and request that the deriving code define only building block functions. The building block functions can be generalized to take on more arguments, though. For example, in the code below, it might "make sense" to allow another_derived::first() to take three arguments. The "mathematically tedious" part of this is the multiplication by 3. Unsurprisingly, it won't allow won't compile unless I comment out the creation of d2. I understand why.
One option is to create different base classes. One would request a single parameter function to be defined, and the other would request a two parameter function to be defined. However, there would be an enormous amount of code being copy and pasted between the two base class' definition of final_result(). This is why I'm asking, so I don't write WET code.
Another option would be to have one pure virtual function, but change the signature so that its implementation can do either of these things. I want to explore this, but I also don't want to start using fancier techniques so that it puts a barrier to entry on the type of people trying to inherit from these base classes. Ideally, if the writers of the base class could get away with barely knowing any c++, that would be great. Also, it would be ideal if the inheritors didn't even have to know about the existence of related classes they could be writing.
#include <iostream>
class base{
public:
virtual int first(int a) = 0;
int final_result(int a) {
return 3*first(a);
}
};
class derived : public base {
public:
int first(int a) {
return 2*a;
}
};
class another_derived : public base {
public:
int first(int a, int b) {
return a + b;
}
};
int main() {
derived d;
std::cout << d.final_result(1) << "\n";
//another_derived d2; // doesn't work
return 0;
}
Not sure it matches exactly what you want, but with CRTP, you might do something like:
template <typename Derived>
struct MulBy3
{
template <typename... Ts>
int final_result(Ts... args) { return 3 * static_cast<Derived&>(*this).first(args...); }
};
class derived : public MulBy3<derived> {
public:
int first(int a) { return 2*a; }
};
class another_derived : public MulBy3<another_derived > {
public:
int first(int a, int b) { return a + b; }
};
With usage similar to
int main() {
derived d;
std::cout << d.final_result(1) << "\n";
another_derived d2;
std::cout << d2.final_result(10, 4) << "\n";
}
Demo

In C++, is it possible to "overload" an object which is a member of another class?

I have a class driver which does a bunch of computations based on a member, which is an object of another class computation_A. The header for driver looks like:
// driver.hpp
#ifndef DRIVER
#define DRIVER
class driver
{
public:
// Making this public may be considered bad practice but this is for illustration purposes only:
computation_A compute;
void do_computation_1();
void do_computation_2();
};
#endif
The source looks like:
// driver.cpp
void driver::do_computation_1()
{
compute.do_something;
// use the results somehow
}
void driver::do_computation_2()
{
compute.do_another_thing;
// use the results somehow
}
In reality, the source is large and contains many calls to members of compute.
Now, I want driver to be able to support another kind of computational class, computation_B, based on some run-time criterion, e.g. a boolean switch bool use_B.
computation_B will have all the same function names as computation_A, but different functionality (e.g. maybe computation_A and computation_B both derive from an abstract class computation - I have some flexibility here).
Furthermore, all subsequent function calls in driver.cpp will be identical. For example, if use_B is set to true (maybe in an Initialize method), then compute.do_something in driver::do_computation_1 will do the thing defined in computation_B. In other words, nothing actually changes in driver.cpp, it just calls all the same functions but of a different class.
I suppose I'm looking for a way to overload compute.
Is there a way for me to achieve this without making significant changes to driver.cpp? I don't mind making changes to driver.hpp, but intuitively I feel that I shouldn't have to rewrite all the same functions in driver.cpp.
As a solution, the first thing that comes to mind is to use templates somehow. But I can't figure out how. My understanding is that templates kick in at compile time, but the value of use_B isn't known until run time (e.g. it is a user input).
Another option is to declare compute as a pointer to an abstract class computation. Then, later on, point compute to the members compute_A or compute_B of classes computation_A or computation_B, respectively, depending on use_B. This would require me to change all function calls compute.do... to compute->do.... This is pretty easy to do I guess, but I'm wondering if there's a better solution (I'm not a very experienced coder, and I have found that there's always a better way than what I think is a good way...)
Thanks.
There are many different approaches. Below few of them aiming at low number of
changes in driver.cpp file. Note that form is very terse and skeleton.
Case 1 --- You know types at compile time. Simple template based solution.
struct mult
{
int a;
double do_work(int b) { return a * b; }
};
struct add
{
double a;
double do_work(int b) { return a + b;}
};
template <class C> struct driver
{
C c;
int x;
void foo() { std::cout << c.a << "|" << c.do_work(x) << "\n"; }
};
// ...
driver<add> a(1);
driver<mult> m(1.0);
a.x = 10;
m.x = 20;
a.foo();
m.foo();
Case 2 --- you know types only at runtime --- virtual functions look like best solution
struct base
{
virtual double& a() = 0;
virtual double do_work(int b) = 0;
virtual ~base() {};
};
class mult : public base
{
double a_; // note that keeping int here would make impl of a() complicated
public:
mult(double d) : a_(d) {};
double& a() override { return a_; }
double do_work(int b) override { return a() * b; }
};
class add : public base
{
double a_;
public:
add(int i) : a_(i) {};
double& a() override { return a_; }
double do_work(int b) override { return a() + b;}
};
// ...
driver a(1), m(1.0);
a.x = 10;
m.x = 20;
a.foo();
m.foo();
Subcase A --- you don't have strong need to keep add/mult inside driver (99% of cases)
struct driver
{
driver(int i) : c(std::make_unique<add>(i)) {}
driver(double d) : c(std::make_unique<mult>(d)) {}
// if copyability is needed then depending on circumstances
// add copy constructor or replace uniqe_ptr with shared_ptr
std::unique_ptr<base> c;
int x;
void foo() { std::cout << c->a() << "|" << c->do_work(x) << "\n"; }
};
std::vector<driver> v;
Subcase B --- you have strong reasons to keep add/mult directly within driver
(such strong reason can be e.g. measured unacceptable degradation in performance)
union amu // this exposes a and m, you may want encapsulate amu in class
{
add a;
mult m;
amu(int i) : a(i) {};
amu(double d) : m(d) {};
base& operator*() {return *static_cast<base*>(&a);}
base* operator->() {return static_cast<base*>(&a);}
~amu() {static_cast<base*>(&a)->~base();};
};
struct driver
{
driver(int i) : c(i) {}
driver(double d) : c(d) {}
amu c;
int x;
void foo() { std::cout << c->a() << "|" << c->do_work(x) << "\n"; }
}

polymorphism and encapsulation of classes

I'm trying to take advantage of the polymorphism in c++, but I'm from a c world, and I think what I've done could be done more cleverly in a OOP way.
I have 2 classes that has exactly the same public attributes, and I want to "hide" that there exists 2 different implementations. Such that I can have a single class where I can use the member functions as If i were accessing the specific class.
An very simple implementation of what I'm trying to accomplish is below:
#include <iostream>
class subber{
private:
int id;
public:
int doStuff(int a,int b) {return a-b;};
};
class adder{
private:
int id;
public:
int doStuff(int a, int b) {return a+b;};
};
class wrapper{
private:
int type_m;
adder cls1;
subber cls2;
public:
wrapper(int type) {type_m=type;};//constructor
int doStuff(int a, int b) {if(type_m==0) return cls1.doStuff(a,b); else return cls2.doStuff(a,b);};
};
int main(){
wrapper class1(0);
std::cout <<class1.doStuff(1,3) <<std::endl;
wrapper class2(1);
std::cout <<class2.doStuff(1,3) <<std::endl;
return 0;
}
I have 2 classes called "subber" and "adder" which both have a member function called doStuff, which will either subtract of add 2 numbers.
This I wrap up in a class "wrapper", which has both "adder" and "subber" as private variables, and a doStuff public member function. And given which value I instantiate my "wrapper" class with, my "wrapper" class will simply relay the "doStuff" to the correct class.
This code does of cause work, but I would like to avoid instatiating both "subber" and "adder" in my wrapper class, since I will only need of them in each of my "wrapper" classes.
Thanks
There are many ways to do it. Through a Factory for example.
But to keep it simple - make a base abstract class that defines the interface, and derive your classes from it to implement the functionality. Then you only need to make the distinction once, when you create the class, after that you don't care, you just call the interface functions.
your code would look something like that.
class DoStuffer
{
public:
virtual int doStuff(int, int)=0;
virtual ~DoStuffer(){}; // Because Tony insists:-) See the comments
}
class subber: public DoStuffer{
public:
virtual int doStuff(int a,int b) {return a-b;};
};
class adder: public DoStuffer{
public:
virtual int doStuff(int a, int b) {return a+b;};
};
int main(){
DoStuffer *class1 = new adder();
DoStuffer *class2 = new subber();
std::cout <<class1->doStuff(1,3) <<std::endl;
std::cout <<class2->doStuff(1,3) <<std::endl;
delete class1; // don't forget these:-)
delete class2;
return 0;
}
This is one of the more idiomatic ways to use the C++ class system to accomplish what you want. Both adder and subber publicly inherit from wrapper, which is now an abstract base class. The doStuff method is now a (pure) virtual function. And instead of being a simple instance of wrapper, the "encapsulated" object is now a reference to a wrapper.
#include <iostream>
class wrapper {
public:
virtual int doStuff(int a, int b) = 0;
};
class subber : public wrapper {
public:
virtual int doStuff(int a,int b) {return a - b;}
};
class adder : public wrapper {
public:
virtual int doStuff(int a, int b) {return a + b;}
};
int main(){
// actual objects
adder impl1;
subber impl2;
// in real code, the wrapper references would probably be function arguments
wrapper& class1 = impl1;
std::cout << class1.doStuff(1,3) << std::endl;
wrapper& class2 = impl2;
std::cout << class2.doStuff(1,3) << std::endl;
return 0;
}
(Not using any factory pattern in this example, since it's not obvious that it's needed or what the question is about.)
Exactly what was last said.
Make a base class, and have a virtual function |doStuff| in it.
Then you can derive any number of classes out from it, all have to implement the above virtual function, in whatever way they want to.
Then you can just do the following
BaseClass *object1 = new DerivedClass1();
BaseClass *object2 = new DerivedClass2();
..
You can even do
object1 = object2;
And then they point to the same object (i.e. an object of type |DerivedClass2|)
But remember, when you do objectn->doStuff(), the function that will be executed will be what the pointer points to at run-time, and not at compile time.
i.e. if I do object1->doStuff() DerivedClass2's doStuff will be called because we already did `object1 = object2;
You may want to Google and read about
Polymorphism/ Run-time Polymorphism
Virtual Functions in C++
You can read Factory Method, which is something that is known as a Design Pattern, but later in life.
Thanks
The classic run-time polymorphic approach is:
struct Operation
{
virtual ~Operation() { } // guideline: if there are any virtual functions,
// provide virtual destructor
virtual int doStuff(int, int) const;
};
struct Subber : Operation
{
int doStuff(int a, int b) const { return a - b; }
};
struct Adder : Operation
{
int doStuff(int a, int b) const { return a + b; }
};
enum Operations { Add, Subtract };
struct Operation* op_factory(Operations op)
{
if (op == Add) return new Adder;
if (op == Subtract) return new Subber;
throw std::runtime_error("unsupported op");
}
int main()
{
Operation* p1 = op_factory(Add);
std::cout << p1->doStuff(1,3) <<std::endl;
Operation* p2 = op_factory(Subtract);
std::cout << p2->doStuff(1,3) <<std::endl;
delete p1;
delete p2;
}
From the Standard 5.3.5/5 "In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand's dynamic type and the static type shall have a virtual destructor or the behavior is undefined.", which is why you must use the virtual keyword on the base class destructor.
It's noteworthy that in your example the type of operation to perform was communicated to the wrapper class using a function argument of 0 or 1... this is what suggests you want run-time polymorphism. For example, if the 0 or 1 value was based on a command line argument, file content, keyboard input etc., then the factory method above can pass a corresponding Add or Subtract value and receive an appropriately-behaving object derived from Operation. This concept of creating an instance of a run-time polymorphic type based on run-time values is known as a factory.
If you really only need compile-time polymorphism, you can do some interesting things with templates such as:
template <class Operation>
void output(int a, int b)
{
std::cout << Operation::doStuff(a, b) << std::endl;
std::cout << Operation::doStuff(a * 10, b * 10) << std::endl;
std::cout << Operation::doStuff(a * 100, b * 100) << std::endl;
}
int main()
{
output<adder>(1, 3);
output<subber>(1, 3);
}
FWIW, your approach is probably slightly faster than the virtual function approach (as it can potentially do more inlining), but not as clean, extensible, maintainable or scalable.
I think what you're looking for is virtual functions. If you declare a function virtual in your base class, you can do things like make a vector containing multiple objects derived from your base class, but when you call on a particular object it will execute it's own method.

Weird casting behaviour

could somebody explain the output of the code.
#include <iostream>
using namespace std;
class First {
public:
int a;
First() {};
First(int a) {
this->a = a;
}
int getA() {
return a;
}
virtual int getB() {
cout << "getB() from super class..." << endl;
return 0;
}
};
class Second : public First {
public:
int b;
Second(int b) {
this->b = b;
}
int getB() {
cout << "getB() from child class..." << endl;
return b;
}
};
int main() {
First* t = new Second(2);
First* cTest = dynamic_cast<First*>(t);
cout << cTest->getB() << endl;
}
I expected the method of the super class would be called because of the casting to First.
thanks in advance
regards sebastian
The function getB() is virtual in the base class, so you get the derived implementation no matter whether you have a pointer-to-base or pointer-to-derived.
(That's the whole purpose of polymorphism.)
A dynamic cast up the hierarchy doesn't change the fundamental fact that you're still pointing at a B. In particular, it doesn't change the vtable used to find the implementation of getB() that will be used.
Typically, you only need dynamic_cast() to go down an inheritance hierarchy, not up.
There only exists one object, and that is of type Second.
To get the behaviour you are looking for, you are going to have to create a copy and slice it:
First cTest = static_cast<First>(*t);
cout << cTest.getB() << endl;
You aren't changing anything with your cast. You are casting a First* to a First*, which is simply an assignment. Since t is a Second with = new Second(2), you have overridden the virtual table with the child's entries, so it will call the child's methods rather than the parents.
cTest is simply a pointer-to-First which points to the exact same object that t does, because cTest and t contain the same memory address, at which exists a Second object, which is why the Second's method is called.

Double dispatch without knowing the full hierarchy

I would like to implement the following thing in C++:
I would like to have a bunch of child classes of a single class with the ability to call a function that takes a pair of objects of any of these types. There is supposed to be a generic implementation that is called for mixed types or the base type and specialised implementations which get called if two objects of the same derived type are used as arguments.
As far as I know, this is a classic application of double dispatch. However, I have the following constraint:
It must be possible to derive new classes from the existing ones and add new pair-functions for these new classes without changing existing classes, for instance in an external library..
The approach I proposed in my last question is faulty, and the solution proposed there only works for types that are known at the time when the base class is written.
Any suggestion on how to implement this? Is that even possible?
Update: Code says more than a thousand words. The following approach works:
#include <iostream>
class B;
class A
{
public:
virtual void PostCompose(A* other)
{
other->PreCompose(this);
}
virtual void PreCompose(A* other)
{
std::cout << "Precomposing with an A object" << std::endl;
}
virtual void PreCompose(B* other);
};
class B : public A
{
public:
using A::PreCompose;
virtual void PostCompose(A* other)
{
other->PreCompose(this);
}
virtual void PostCompose(B* other)
{
other->PreCompose(this);
}
virtual void PreCompose(B* other)
{
std::cout << "Precomposing with a B object" << std::endl;
}
};
void A::PreCompose(B* other)
{
PreCompose((A*)other);
}
int main()
{
B b;
A* p = &b;
p->PostCompose(p); // -> "Precomposing with a B object"
}
but it requires knowledge of B when implementing A. Is there a better way?
Since the derived classes only need to detect if the parameter type matches the object type, you can just use a straightforward check.
virtual void foo( base *argument_base ) {
if ( derived *argument = dynamic_cast< derived * >( argument_base ) ) {
argument->something = pair_match_foo;
} else {
base_class::foo( argument_base );
}
}