virtual operator +

H

Hunk

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
 
Y

year1943

I ws wondering if there is a way to implement operator+ in case of
virtual classes.
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 you call operator + in context where compiler doesn't know the real
(dynamic, runtime) types of lhs & rhs objects of op+, it of course
would expect that return type of op+ is as specified in operator + for
used static types of lhs, rhs.
Example: for (Base*, Base*), if op+ returns Base, compiler expect
Base, and reject you to assign Base to Derived, as usual.
If you sure your Base-s in this context would always be pointers/
references to real (dynamic, runtime) Derived objects, you may
dynamic_cast<Derived>(result_of_op_plus) and assign. But this is you
work of'course, compiler shouldn't allow you convert Base to Derived
by default, automatically.
 
V

Victor Bazarov

Hunk said:
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

Don't think much of overriding the operator+. Let it live in the base
class, and let it return the Base_string. Overload the _assignment_
operator in each of the derived classes:

template<size>
class Char_string : Base_string {
Char_string& operator=(Base_string const&) {
// do what's needed
return *this;
}
};

template<size>
class Hash_string: Base_string {

Hash_string& operator=(Base_string const&) {
// do what's needed
return *this;
}
};

That way you can assign the result of the operator+ to the correct
object. And the proper operator= function will be called. Do in it
what you have to.

V
 
Y

year1943

Also note, op+ for (Base&, Base&) should really return Derived type -
so, if you want to have not only one
Derived operator +(Base&, Base&)
that always return Derived for any given Base*s, but family of
Base* operator +(Base&, Base&)
that returns Derived only for Derived args, op should return result
not by value...
 
H

Hunk

Don't think much of overriding the operator+. Let it live in the base
class, and let it return the Base_string. Overload the _assignment_
operator in each of the derived classes:
If operator+ lives in the base class it would lead to errors.
For eg implementation for operator+ would look like

Base_string operator + (const Base_string& p_string_r) const
{
Base_string temp_str = *this;
temp_str.append(p_string_r.get_string()); //
return temp_str;
}
The problem with this is , the get_string and append are all virtual
in the base class... they would be overridden in the derived class...
for eg get_string for base class is meaningless as it does not contain
any data. So this would bomb out here itself. So am not sure this idea
would work.
 
N

Noah Roberts

Hunk said:
If operator+ lives in the base class it would lead to errors.
For eg implementation for operator+ would look like

Base_string operator + (const Base_string& p_string_r) const
{
Base_string temp_str = *this;
temp_str.append(p_string_r.get_string()); //
return temp_str;
}
The problem with this is , the get_string and append are all virtual
in the base class... they would be overridden in the derived class...
for eg get_string for base class is meaningless as it does not contain
any data. So this would bomb out here itself. So am not sure this idea
would work.

I can imagine that in some cases what you are saying would be true, it
isn't a given. It is quite common to have a base class function call
various pure virtuals within itself that are overridden by descendants.
In pattern-speak we call it a "template method". The only time you
cannot do it is in the constructor.
 
H

Hunk

I can imagine that in some cases what you are saying would be true, it
isn't a given. It is quite common to have a base class function call
various pure virtuals within itself that are overridden by descendants.
In pattern-speak we call it a "template method". The only time you
cannot do it is in the constructor.- Hide quoted text -

- Show quoted text -

So in effect you are saying the scenario i presented would have no
solution?
 
M

Maarten Kronenburg

"Hunk" wrote in message...
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

The STL string destructor is non-virtual for performance reasons (see
comment by Scott Meyers in More Effective C++), so it cannot be derived
runtime polymorphically (for virtual functions you need a virtual
destructor). So you may make such a class yourself with an STL string as a
data member. For a proper runtime polymorphic class, you may have to use the
NVI (NonVirtual Interface) design pattern, see Sutter & Alexandrescu in C++
Coding Standards. You may also look into my runtime polymorphic infinite
precision integer design, that is document N2143 available on:
http://open-std.org/jtc1/sc22/wg21/docs/papers/2007/#mailing2007-01
as it also has arithmetic operators you mention. In the Introduction, in the
section "Classes derived from class integer", you may find an answer to your
question if operator+ should return a base or derived object.
Regards, Maarten.
 
H

Hunk

"Hunk" wrote in message...


The STL string destructor is non-virtual for performance reasons (see
comment by Scott Meyers in More Effective C++), so it cannot be derived
runtime polymorphically (for virtual functions you need a virtual
destructor). So you may make such a class yourself with an STL string as a
data member. For a proper runtime polymorphic class, you may have to use the
NVI (NonVirtual Interface) design pattern, see Sutter & Alexandrescu in C++
Coding Standards. You may also look into my runtime polymorphic infinite
precision integer design, that is document N2143 available on:http://open-std.org/jtc1/sc22/wg21/docs/papers/2007/#mailing2007-01
as it also has arithmetic operators you mention. In the Introduction, in the
section "Classes derived from class integer", you may find an answer to your
question if operator+ should return a base or derived object.
Regards, Maarten.

I would not be using the stl string but a raw character array as data
member in the derived classes. The reason i'm developing in this way
is to better manage my memory footprint and also provide faster access
by use of hash derivation. I'll go through the section and let you
knwo if its relevant
 
M

Maarten Kronenburg

In addition to my previous reply I have to be a bit more precise. In my
integer class the operator+ returns a base object, which can then be
converted back to a derived object by operator=. This is to make equivalent
arithmetic expressions have equivalent results. But this can only be done if
the derived class has no extra data members (in addition to the data members
of the base class), otherwise they would be sliced off. Now when your
derived class would have extra derived data members, this slicing problem
makes things more complicated. In that case you would need also a derived
operator+ which returns a derived object. This would save your derived data
members, but then equivalent arithmetic expressions with both base and
derived objects may lead to unequivalent results. You would have to work
this out for a few used arithmetic expressions to see if that would happen.
Regards, Maarten.
 
H

Hunk

In addition to my previous reply I have to be a bit more precise. In my
integer class the operator+ returns a base object, which can then be
converted back to a derived object by operator=. This is to make equivalent
arithmetic expressions have equivalent results. But this can only be done if
the derived class has no extra data members (in addition to the data members
of the base class), otherwise they would be sliced off. Now when your
derived class would have extra derived data members, this slicing problem
makes things more complicated. In that case you would need also a derived
operator+ which returns a derived object. This would save your derived data
members, but then equivalent arithmetic expressions with both base and
derived objects may lead to unequivalent results. You would have to work
this out for a few used arithmetic expressions to see if that would happen.
Regards, Maarten.

Bull's eye... my base class has no data members and derived class have
all the members
the design is like
class Base_string{};

template<size>
Class Char_string:Base_string
{ char d_the_string[size];
size_t d_size;
};
template<size>
Class Hash_string:Base_string
{ char d_the_string[size];
size_t d_size;
int d_hash; };

so here i'm stuck while overriding the virtual operator+ in the
Base_string as it would mess up what it is pointing to (eg in the
earlier post)
 
M

Maarten Kronenburg

Bull's eye... my base class has no data members and derived class have
all the members
the design is like
class Base_string{};

template<size>
Class Char_string:Base_string
{ char d_the_string[size];
size_t d_size;
};
template<size>
Class Hash_string:Base_string
{ char d_the_string[size];
size_t d_size;
int d_hash; };

so here i'm stuck while overriding the virtual operator+ in the
Base_string as it would mess up what it is pointing to (eg in the
earlier post)

Personally I understand that the hashed string has different addition
behaviour than a normal string. But personally for reasons of simplicity I
would make a single class hash_string which always has a data member int
d_hash, but when d_hash is zero, the class behaves like a normal string, and
I would make the size not a template parameter, but a constructor parameter,
but also use a char type template parameter.
Just as another line of thought:
template<class charT>
class hash_string
{ charT * the_string;
size_t the_size;
unsigned int the_hash;
public:
hash_string( size_t asize, unsigned int ahash = 0 )
: the_size( asize ), the_hash( ahash )
{ the_string = new charT [ asize ];
};
~hash_string()
{ delete [] the_string;
};
Now the member functions and operators like operator+= do a hash only if
the_hash is not zero. You would have to decide what the binary operator+
must do when only one of the arguments the_hash is zero, or when they are
different. This way you don't need derivation at all, which in my opinion in
this case saves you some problems.
Regards, Maarten.
 
H

Hunk

Bull's eye... my base class has no data members and derived class have
all the members
the design is like
class Base_string{};
template<size>
Class Char_string:Base_string
{ char d_the_string[size];
size_t d_size;
};
template<size>
Class Hash_string:Base_string
{ char d_the_string[size];
size_t d_size;
int d_hash; };
so here i'm stuck while overriding the virtual operator+ in the
Base_string as it would mess up what it is pointing to (eg in the
earlier post)

Personally I understand that the hashed string has different addition
behaviour than a normal string. But personally for reasons of simplicity I
would make a single class hash_string which always has a data member int
d_hash, but when d_hash is zero, the class behaves like a normal string, and
I would make the size not a template parameter, but a constructor parameter,
but also use a char type template parameter.
Just as another line of thought:
template<class charT>
class hash_string
{ charT * the_string;
size_t the_size;
unsigned int the_hash;
public:
hash_string( size_t asize, unsigned int ahash = 0 )
: the_size( asize ), the_hash( ahash )
{ the_string = new charT [ asize ];
};
~hash_string()
{ delete [] the_string;
};
Now the member functions and operators like operator+= do a hash only if
the_hash is not zero. You would have to decide what the binary operator+
must do when only one of the arguments the_hash is zero, or when they are
different. This way you don't need derivation at all, which in my opinion in
this case saves you some problems.
Regards, Maarten.- Hide quoted text -

- Show quoted text -

Marteen,
The design you provide necessates that hash be performed outside the
class and be served as a parameter in the constructor. But in my
design, the hash string class itself should provide for computation of
hash. In essence by choosing a hash_string over a char_string , the
user is implying that i have a lot oc comparisons to do hence compare
the strings using the hash value. Usabilitry wise it would behave
identically to char_string. I had a desing using policy classes that
waorked , but the change in design necessated from the fact that a
common interface a.k.a a non-template base_string generic class would
be needed . Now i'm stuck with this overriding of virtual class wich
returns by value paradox. I'll go thrrough the NVI design pattern
hopefully to pick up some clue
 
J

James Kanze

I ws wondering if there is a way to implement operator+ in case of
virtual classes.

In general, polymorphism and operator overloading don't work
well together; operator overloading requires a value type for
the return values. (In cases where it is necessary, the
letter/envelop idiom can be used to may a class with value
semantics act polymorphically.)
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?

Just a general question: if I add a Char_string< 16 > and a
Hash_string< 14 >, what concrete type should the results have?
This is an important aspect of the problem. But not the only
aspect. Typically, for addition if there are N different
derived types, then you have NxN different functions to
implement, each with potentially a different return type (or
different rules for determining the return type).

I'm not sure what the difference is between a Hash_string and a
Char_string, but for just a single hierarchy, where the derived
types only differ in length, you can probably work something out
with templates, e.g.:

template< size_t L, size_t R >
FixedLengthString< L + R >
operator+( FixedLengthString< L > const& lhs,
FixedLengthString< R > const& rhs ) ;

Trying to use polymorphism here, however, will not work.
 
H

Hunk

In general, polymorphism and operator overloading don't work
well together; operator overloading requires a value type for
the return values. (In cases where it is necessary, the
letter/envelop idiom can be used to may a class with value
semantics act polymorphically.)
You are right... learnt it the hard way... you say there is some way
in letter/envelop idiom?
For now i have taken the decision to restrict the user to use only +=.
I know this is a very restrictive
way , but for now i know of no other way to tackle the issue
Just a general question: if I add a Char_string< 16 > and a
Hash_string< 14 >, what concrete type should the results have?
This is an important aspect of the problem. But not the only
aspect. Typically, for addition if there are N different
derived types, then you have NxN different functions to
implement, each with potentially a different return type (or
different rules for determining the return type).

Thats a good question. I would prefer giving a compilation error for
this.
This is for the simple reason that Hash_string data members are
different than
Char_string. So would'nt know which to return
I'm not sure what the difference is between a Hash_string and a
Char_string, but for just a single hierarchy, where the derived
types only differ in length, you can probably work something out
with templates, e.g.:
The difference in Hash_string and Char_string is that the Hash_string
class has a
hash value computed and stored as a data member. So comparisons are
faster as they
would be comparing integers rather than characters.
The generic base_string is required as for the interface class a
generic version is required.
 
A

Alf P. Steinbach

* Hunk:
I ws wondering if there is a way to implement operator+ in case of
virtual classes.

You mean polymorphic 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{
};

Did you really mean to have private inheritance here?

It could be the Right Thing to do, but then in conjunction with some
other way to convert up to 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?

If operator+ returns a Base_string, then assignment of the result to
Base_string (provided there is an accessible assignment operator) works.

Any soultions to the above issue is most welcome

What's the problem?

And why are you talking about using a virtual operator+?

Cheers, &hth.,

- Alf
 
H

Hunk

* Hunk:




You mean polymorphic classes. Yes




Did you really mean to have private inheritance here?
No its a public inheritance , ergo a typo
It could be the Right Thing to do, but then in conjunction with some
other way to convert up to Base_string.






If operator+ returns a Base_string, then assignment of the result to
Base_string (provided there is an accessible assignment operator) works.
It doesnt work in case of virtual as return of operator is by value
(shown below )
Base_string operator + (const Base_string& p_string_r) const
{
Base_string temp_str = *this;
temp_str.append(p_string_r.get_string()); //
return temp_str; // the value would be lost
}
What's the problem?

And why are you talking about using a virtual operator+?
Hope you got it now... in the first post i have specified the design
of the class
 
A

Alf P. Steinbach

* Hunk:
It doesnt work in case of virtual as return of operator is by value
(shown below )
Base_string operator + (const Base_string& p_string_r) const
{
Base_string temp_str = *this;
temp_str.append(p_string_r.get_string()); //
return temp_str; // the value would be lost
}

Well, yeah, that's OK; the comment is just meaningless, however.

What's the problem?

By the way, please don't quote signatures.

Cheers, & hth.,

- Alf
 
H

Hunk

* Hunk:


Well, yeah, that's OK; the comment is just meaningless, however.

What's the problem?

By the way, please don't quote signatures.

Cheers, & hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

The problem is how do we write operator+ for such a class
I have given scenario in the previous post on why it would not work
 
A

Alf P. Steinbach

* Hunk:
The problem is how do we write operator+ for such a class
I have given scenario in the previous post on why it would not work

Quoted signature removed.

PLEASE DON'T QUOTE SIGNATURES, please read the FAQ's items on posting
before posting.

I have no problem implementing classes conforming to what you have
described so far. What is the problem? Do you by chance have some
error on line 478?

Cheers, & hth.,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top