problem when copying with inheritance

Hi,

I have some class in my program, like class A and class B. B is derived from A, like:
1
2
3
4
5
6
7
8
9
10
11
class A
{
public:
    int x;
};

class B : public A
{
public:
    int y;
};


But when I do something like this:
1
2
3
4
B b = B();
b.x = 10;
b.y = 20;
A a = b;

Then a only contains all the members that b had and only where declared in A. So a only contains x which is 10 now, but not y which I want to be 20. Is there another way I can do such a thing? Because I have like a class called MeasuringDevice where all sensors that only fetch a value derive from. I also have a function that takes a MeasuringDevice and ensures that it get written down. The classes that derive from MeasuringDevice all have their own way control that sensor and retrieve the value. But that function does not know at the moment what kind of sensor it got and so it doesn't retrieve that value because it used the virtual function GetValue that is declared in the class MeasuringDevice itself.
I'm not sure if I understand the problem, but have you tried using a polymorphism approach?

That is, let's say you have an abstract base class MeasurementDevice:

1
2
3
4
5
6
7
8
9
10
11
class MeasurementDevice
{
private:
	double value;
	// ...
public:
	virtual void PrintStuff();
	virtual void ControlStuff();
	virtual double Retrieve();
	// ...
};


You can then have concrete classes that inherit from this class, hence conforming to the behaviour of a MeasurementDevice. Let's say we want a Voltmeter.

1
2
3
4
5
6
7
8
9
10
class Voltmeter: public MeasurementDevice
{
private:
	bool canMeasureImpedence; // Other attributes specific to Voltmeters
public:
	void PrintStuff();
	void ControlStuff();
	double Retrieve();
	// ...
};


Now, you can use polymorphism and do the following:

MeasurementDevice * myVoltmeter = new Voltmeter();

You could also have a collection which stores MeasurementDevice objects, with each element of the collection being a Voltmeter or another type of MeasurementDevice. Check out http://www.cplusplus.com/doc/tutorial/polymorphism/ for more info on this idea.

So, to answer your original question, I think you could simply do:

A b = B()

I should say that I'm not as experienced as some of the other guys around here, so we should hear what they have to say about it too :).
But if you have an function like:
1
2
3
4
void printStuff(MeasurementDevice md)
{
    ..........
}

And you want to run that function with a Voltmeter:
1
2
Voltmeter volt();
printStuff(volt);

Then volt would be copied and that copied version can be used inside function printStuff, right?
So md with type MeasurementDeivce would be a copy of what was originally Voltmeter volt. But md doesn't contain canMeasureImpendence, PrintStuff, ControlStuff and Retrieve. It only contains value and PrintStuff, ControlStuff and Retrieve from MeasurementDevice instead of the ones from Voltmeter, which I need. That's my problem.
Maybe I need to add a template to the function and case md into the type given with the template?
Ok I think I understand what you're after now. As a matter of fact there's another thread going on at the moment that might help. See: http://www.cplusplus.com/forum/general/21880/

As Bazzy talks about, you could create a printStuff method like you wrote in your last post, and in there do a dynamic cast back to a Voltmeter (then maybe call a method designed to take a Voltmeter object). Then, you should be able to access the canMeasureImpedence field etc.

But it doesn't make much sense to me to make a method 'printStuff' which accepts an instance of a base class, and then try and do things with that instance that aren't common to all of the inherited classes. Maybe there's a better way to design what you're trying to do?
Maybe, but I see the Voltmeter class just like a driver. I use the API from the company where I bought the sensors from to make a class derived from MeasurementDevice to 'talk' to that sensor. At the moment I only support Phidget sensors but there gonna be more. I want all those sensors to be able to be used the same. I chose inheritance to avoid checking the sensor type for every method/thing, but maybe there is a better design.
When using polymorphism, it's important not to make copies of objects, particularly to base classes. Otherwise the copies will lose the extra information that the derived instances contained.
The proper way to implement printStuff() would be
1
2
3
void printStuff(MeasurementDevice &md){ //pointers also work
    std::cout <<md.get_measurement_string()<<std::endl;
}

This way, anything derived from MeasurementDevice can be passed to the function without losing any information
If md was an object copied from a derived class instance, MeasurementDevice::get_measurement_string() would be called instead of, say, Voltmeter::get_measurement_string(), which is what you probably wanted.
In order for all this to work, get_measurement_string() must have been declared virtual in the base class.
OK thanks! That should help!
The specific problem here is that printStuff should take a reference or a pointer. The object is being sliced during the copy and only the object of the base class type gets copied. Even if the copy was possible there you don't really want to copy the object anyway. There is no point in copying it.

This is on the clone pattern which explains how to copy objects properly when there is inheritance and you don't want the derived class dependency. It is a good read even though it is not directly related to the printStuff function.
http://cplusplus.com/forum/articles/18757/
Last edited on
Topic archived. No new replies allowed.