Re: virtual operator +
Hunk wrote:
Hi
I ws wondering if there is a way to implement operator+ in case of
virtual classes.
Here's the problem. I have to have a base string class from which two
classes (normal char string and a hash string class ) are derived. The
two derived classes are template classes specifying the sizes. The
base class is a non-template class so that it can be used generically
in the interface classes. the design would look like
class Base_string {
};
template<size>
class Char_string : Base_string {
};
template<size>
class Hash_string: Base_string{
};
So that in the interface class of the application he can use just the
generic Base_string to access the functions and doesnt have to know
whether its a Char or hash string
The issue is in implementing the operator+ . Since all the methods are
virtual in the base class and it should call the desired methods
polymorphically, operator+ is a challenge as it returns a Base_string
object
So if I have something like
Char_string<24> char_string1("Hello");
Char_string<24> char_string2("world");
Char_string<24> char_result;
Base_string* base_a = &char_string1;
Base_string* base_b = &char_string2;
Base_string* base_r = &char_result;
i wouldnt be able to do
*base_r = *base_a + *base_b; as the operator+ would return a
Base_object?
Any soultions to the above issue is most welcome
If it's just two derived classes, you might get away with something like
this:
#include <iostream>
#include <tr1/memory>
#include <cassert>
class Base {
public:
Base ( void ) {}
virtual
void some_method ( void ) const = 0;
};
class DerivedA : public Base {
public:
DerivedA ( void )
: Base()
{}
virtual
void some_method ( void ) const {
std::cout << "DerivedA\n";
}
};
class DerivedB : public Base {
public:
DerivedB ( void )
: Base ()
{}
virtual
void some_method ( void ) const {
std::cout << "DerivedB\n";
}
};
class Sum {
enum type { derived_a, derived_b };
typedef std::tr1::shared_ptr<Base> pointer;
pointer the_ptr;
type the_type;
public:
Sum ( Base const & lhs, Base const & rhs )
: the_ptr ()
{
if ( ( dynamic_cast<DerivedA const *>( &lhs ) != 0 )
&&
( dynamic_cast<DerivedA const *>( &rhs ) != 0 ) ) {
the_ptr = pointer( new DerivedA () );
the_type = derived_a;
}
if ( ( dynamic_cast<DerivedB const *>( &lhs ) != 0 )
&&
( dynamic_cast<DerivedB const *>( &rhs ) != 0 ) ) {
the_ptr = pointer( new DerivedB () );
the_type = derived_b;
}
assert( the_ptr != 0 );
}
operator Base & ( void ) {
return ( *the_ptr );
}
operator Base const & ( void ) const {
return ( *the_ptr );
}
operator DerivedA & ( void ) {
assert( the_type == derived_a );
return ( static_cast<DerivedA &>( *the_ptr ) );
}
operator DerivedA const & ( void ) const {
assert( the_type == derived_a );
return ( static_cast<DerivedA const &>( *the_ptr ) );
}
operator DerivedB & ( void ) {
assert( the_type == derived_b );
return ( static_cast<DerivedB &>( *the_ptr ) );
}
operator DerivedB const & ( void ) const {
assert( the_type == derived_b );
return ( static_cast<DerivedB const &>( *the_ptr ) );
}
void some_method ( void ) const {
the_ptr->some_method();
}
};
Sum operator+ ( Base const & lhs, Base const & rhs ) {
return ( Sum( lhs, rhs ) );
}
void test ( Base & b ) {
b.some_method();
}
int main ( void ) {
DerivedA a1;
DerivedA a2;
( a1 + a2 ).some_method();
DerivedA a;
a = a1 + a2;
DerivedB b1;
DerivedB b2;
test( b1 + b2 );
DerivedB b ( b1 + b2 );
}
The user-defined converions can lead to ambiguities, and there are probably
some other problems.
Question: what is the purpose of a common base class for these two string
types? Are users really supposed to use Base_string* polymorphically? If
you don't really need runtime polymorphism, the string classes could be
independent and common functionality can be supplied by templates and
overloaded functions.
Best
Kai-Uwe Bux