Reputation: 5913
I have a huge C++ code base I'm working with.
I want to introduce a new subclass, and use it in a variety of different contexts, however my Java trained mind is having trouble with this in C++.
I wish to minimize code changes. So, my main class of interest (BAR
below) has a member variable of class FOO
. I wish to make a subclass of FOO
called FOOSUBCLASS
. In java this is trivial. Objects are stored by reference by default. This code does not do that (as seen below) can I massage this code, without changing interfaces (and without introducing references) and still make my application work?
class FOO {
};
class FOOSUBCLASS : FOO {
public:
FOOSUBCLASS(const int id) {_id = id;}
private:
int _id;
};
class BAR {
public:
BAR(const FOO foo) { _foo = foo;}
private:
FOO _foo;
};
Below, is my main:
FOOSUBCLASS fsc(1);
BAR b(fsc);
But this doesn't compile in VS2005. It says:
'type cast' : conversion from 'FOOSUBCLASS *' to 'const FOO &' exists, but is inaccessible
Get same compiler error if I add the obvious other constructor to BAR
BAR(const FOOSUBCLASS foo) { _foo = foo;}
My understanding of C++ is that it will copy the data from FOOSUBCLASS
into an object of class FOO
. (using the assignment operator, or a class overridden version of it) But in my case, I have additional member variables in FOOSUBCLASS
(and some overridden member functions) so I just don't want it to do that. I want my member variable _foo
to truly be of type FOOSUBCLASS
in some contexts, and FOO
in others. Is this even possible?
Thanks for your thoughts.
Upvotes: 3
Views: 2326
Reputation: 6914
First in C++ classes by default use private
to inherit from their base classes, this means that FOOSUBCLASS
is a FOO
but conversion is internal and is not accessible to you. So first convert class FOOSUBCLASS : FOO
to class FOOSUBCLASS : public FOO
and second is in Java every this is reference so you can say
FOOSUBCLASS fs;
FOO f = fs;
but in C++ we have references and non-references and using FOO f
create a non-reference that is actually an object so FOO f = fs
only copy FOO
part of fs
into f
and does not cause a FOO
reference to a FOOSUBCLASS
to achieve this you should use pointer or reference or smart pointers. For example you can say:
FOOSUBCLASS* fs = new FOOSUBCLASS;
FOO* f = fs; // Use pointer is OK
FOO& rf = fs; // A reference of fs as a FOO
std::auto_ptr<FOO> spf( fs ); // OK, but for this destructor must be virtual
Upvotes: 1
Reputation: 1334
Further to user sehe, consider passing a reference rather than passing by value to constructor of BAR.
class BAR {
public:
BAR(const FOO& foo) { _foo = foo;}
private:
const FOO& _foo;
};
Upvotes: 0
Reputation: 1334
You can't do it the way you've written it now, sorry. This is called "slicing", and more info about it can be found here: What is object slicing?
If you want your _foo
member to be polymorphic, you'd need to use a pointer or a reference. Be aware of lifetime management when you do things like this of course.
Upvotes: 2
Reputation: 393799
Make the base class public
class FOOSUBCLASS : public FOO {
public:
FOOSUBCLASS(const int id) {_id = id;}
private:
int _id;
};
Also, beware of slicing in the BAR
constructor
Assign to pointer/reference to avoid that:
class FOO
{
};
class FOOSUBCLASS : public FOO
{
public:
FOOSUBCLASS(const int id) : _id(id) {}
private:
int _id;
};
class BAR
{
public:
BAR(const FOO& foo) : _foo(foo)
{
}
private:
FOO& _foo;
};
Note: I used initializer-list syntax instead of assignments in the constructor body.
Upvotes: 2