Is it possible to "override" a variable type in an inherited class? I have a situation where I have a base class with a class-type member. I have a number of sub-classes derived from this base class, and 99% of them work fine as-is. However, in one I need to replace said member with a different data type that is derived from the original data type - basically I need to change the way it presents its data slightly. All the functions working with this member in the base class, however, would continue to work fine - as the new member is derived from the old - so I don't want to have to make a brand-new member in my derived class and duplicate all the functions in it using the new member. Does this make sense? Is it possible? I tried just making a member with the same name, but all that does is give me two copies of the member, with the base-class one (on which all the base-class functions continue to operate) being hidden by the child-class one, as I rather expected. Thanks!
That is basically the only way to do it (hiding it) unless you want to create a template for that type and define the template for each subclass. Read up on templates if you want to do this (although I think that hiding it is fine, as long as it is very obvious which one you are using...you might be better off just making a different type with a different name though.)
It sounds to me that you should have a base class that your current "base" class inherits from and adds the member that you want to hide... Hiding a member should raise all kinds of red flags; your design is flawed. I suggest white-boarding your classes and their members; it should straighten things right out.
I'm not familiar with the term white-boarding - I'll have to google that :) As far as hiding the other variable goes, that doesn't work because then all the base class functions work on the hidden variable, not the child-class variable (as I think I mentioned). I need the base-class functions to work on the child-class copy, as I mentioned. So when the base-class function to populate the member, for example, runs, it populates the member of the base class, NOT the member of the child class, which is what I need. Making the different type with a different name does, of course work, but at the expense of having to re-implement all my base class functions that deal with the member in question. Not a nice solution.
You could use a class template, however then you'd need to have all base class member functions in the .h file, and the derived classes would have a different parent class. To get around the latter problem you could derive from yet another parent class. This is probably what firedraco was talking about in his post.
This is not an ideal solution, obviously. It might cause more design headaches than it's worth... but I felt it's worth mentioning anyway.
The idea: Assuming you have base class 'B' which has a member var. Most classes (I) represent this var as type 'int', but you need a special class 'S' which has it as type short instead:
// template base class
template <typename T>
class B
{
virtualvoid func();
T member;
};
// most derived classes (I)
class I : public B<int>
{
virtualvoid func();
};
// special derived class (S)
class S : public B<short>
{
virtualvoid func();
};
The problem with this is that 'B' is no longer a class name (it's a class template -- as far as the compiler is concerned, I and S have completely seperate base classes.... B<int> and B<short> are totally different). So if you have areas on code which take a pointer to the base class, you won't be able to employ this method without an additional tweak. That tweak is to derive B from another, pure virtual class:
1 2 3 4 5 6 7 8 9
class A
{
virtualvoid func() = 0;
};
template <typename T>
class B : public A
{
//...
Now 'A' is the common base class to all types, and the type of your member is variable (templated)
class Base
{
public:
Base(){ data_ptr = new Base_data_type ; }
// don't forget to implement copy constructor etc.!
void do_something() { std::cout << data_ptr -> data_member ;}
private:
Base_data_type* data_ptr ;
} ;
struct Derived_data_type : Base_data_type
{
public:
Derived_data_type(Base_data_type* start_data) {
//copy the necessary data into your structure
}
/* alter whatever you want. You maybe want to use some virtual methods. */
}
;
class Derived : public Base
{
public:
Derived():Base()
{
Base_data_type* tmp = data_ptr; // so that we can later free the memory
data_ptr = new Derived_data_type (tmp) ; // so that we can use the initialisations made on the old data
delete tmp ; // now we don't need the old data any more...
}
// don't forget to implement copy constructor etc.!
private:
base_data_type* data_ptr ;
} ;
So each method now operates on the new data structure.
Thanks for all the suggestions. Just using pointers worked like a charm. Actually, I feel kinda embarrassed now that I didn't think of that at first, but oh well. Thanks again!