3

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.

John
  • 5,735
  • 3
  • 46
  • 62
  • `and without introducing references` Why? – Jesse Good Oct 11 '12 at 23:20
  • @JesseGood because I want to avoid making huge changes in the code base. This is a million line code base, and introducing references will change the lifecycle management of the application. But, based upon answers below, it looks like I'm completely stuck with having to do that.... – John Oct 11 '12 at 23:22
  • The only other option is to add another member `FOOSUBCLASS myfoosub;` and a `BAR(const FOOSUBCLASS)` constructor. – Jesse Good Oct 11 '12 at 23:33

4 Answers4

2

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.

sehe
  • 374,641
  • 47
  • 450
  • 633
2

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.

Community
  • 1
  • 1
Tom W
  • 1,304
  • 8
  • 9
1

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
BigBoss
  • 6,904
  • 2
  • 23
  • 38
0

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; };

bobestm
  • 1,334
  • 1
  • 9
  • 8