Design Question

S

Suki

Hi all,
I'm facing a rather strange design problem. Let me explain it.

I'm writing an application, which deals with strings extensively. So
decided to write a new string class (CXString say) for my application.
But majority of its member functions are the same as the ones in
std::string class.

So I've decided to derive CXString from std::string class. No problem
till now. But now i'm facing with the problem of invoking CXString
class.

My class looks some thing like this.

class CXString : public std::string
{
public:
CXString() ; // No argument constructor ;
CXString (const std::string&) ; // One argument constructor

// Member functions goes here .
} ;


Now my question is, is it valid to invoke a derived class with a base
class object.??


I'd like to call my CXString object like this.

CXString my_str ;

my_str.find_first_of (...) // member function from std::string class
my_str.my_string_function (...) // Member function from CXString class.

What I'd like to know is whether there's any problem with my design. If
not suggest me a new design.

Thanks in advance,
Surya


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
T

TB

Suki sade:
Hi all,
I'm facing a rather strange design problem. Let me explain it.

I'm writing an application, which deals with strings extensively. So
decided to write a new string class (CXString say) for my application.
But majority of its member functions are the same as the ones in
std::string class.

So I've decided to derive CXString from std::string class. No problem
till now. But now i'm facing with the problem of invoking CXString
class.

Actually, std::string does not have a virtual destructor, hence
deriving is a no-no.

TB
 
R

Risto Lankinen

TB said:
Actually, std::string does not have a virtual destructor, hence
deriving is a no-no.

Close but no cigar. The real no-no is deleting a derived instance
thru a pointer to the base type [having no virtual destrutor].

One way to reduce the risk is to use private inheritance.

- Risto -
 
T

technator

Now my question is, is it valid to invoke a derived class with a base
class object.??

This is not possible. If you have a base class object, then there is no
"derived sub-obect" in it.

There is no problem with your design. If you override base class
function, then this would be called. Otherwise, the derived class
function is called.

Technator


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
R

rishin

Although your code looks workable i dont think you should derive from
stl classes.
Try making a container class with delegations to std::string where you
need to
use std::string functionality.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
B

Bronek Kozicki

Suki said:
I'm writing an application, which deals with strings extensively. So
decided to write a new string class (CXString say) for my application.

Please provide some rationale for this design decision, as it does not
seem obvious to me at all. In C++ more typical approach is to use
namespace scope functions (that is not members of any class) that deal
with strings. For example, function that removes leading and trailing
whitespace from string would be:
template<typename Char> void trim(std::basic_string<Char> &);
and/or:
template<typename Char> std::basic_string<Char> trim_copy(const
std::basic_string<Char>&);

For rationale see excellent articles by Herb Sutter
http://www.gotw.ca/publications/mill02.htm and
http://www.gotw.ca/gotw/084.htm
(preferably in this order).

Inheritance from concrete class in order to extend its interface is
typical in OOP languages (those that impose OOP, like Java), but not is
C++ (which is multiparadigm language, not OOP one). Furthermore, in C++
it might be unsafe, if inherited destructor is public and non-virtual
(as is the case with std::string).


B.



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
M

Maciej Sobczak

Suki said:
So I've decided to derive CXString from std::string class.
What I'd like to know is whether there's any problem with my design.

Yes, there is.

Your new class uses public inheritance from std::string, whereas from
the design point of view it is not a std::string (or is it?).
Is your new class substitutable where std::string is expected (in the
Liskov sense)? What behavior do you expect when calling, for example,
fun(std::string &s) with the object of your new class? Is this expected
behavior different from the one you get when using just std::string in
the first place?

Your new class cannot override any virtual functions from std::string,
because there aren't any (so you don't really *specialize* std::string).
Instead, it adds some new functions to those that are already in
std::string. The problem is that your new function(s) will use *only*
public interface of std::string (it cannot use private interface and
there is nothing protected in std::string) - this means that your new
class provides something that *might* be useable with objects of regular
std::string class, but they will not be, just because you have coupled
your new functions with the new class only.
What will you do when you (or someone else in the same project) will
need to excercise the new functionality on regular std::string objects?
Do you want programmers to cast std::string to the derived class? Or do
you want them to implement the same new functionality again, just
because they cannot use the one that you've needlessly put in your new
class?

And last but not least, you have decided to write your own class,
because... apparently for some reason. For example, you believe that you
can benefit from some domain-specific optimization opportunities (which
is OK). And you decided *not* to use std::string in your project. That's
still OK. But by derivation you have exactly coupled yourself to
std::string, which is what you decided *not to use* in the first place.

No matter how you look at it, it's broken.

Use std::string in your project and if you need some "additional"
functionality, implement it as a *separate function*. If you have many
such functions, keep them in some namespace. That's it.
Don't write new classes if they aren't.


--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
C

Carl Barron

Suki said:
What I'd like to know is whether there's any problem with my design. If
not suggest me a new design.

no problem if CXString contains no data and it is
properly documented so that one does not derive
from CXString and then destructs as a CXString
or an std::string after addding data.

If no data is added it is theoretically possible to have
the same slicing problem, but it is not guaranteed.

safer is containment.
class CXString
{
std::string data;
public:
// ctors
CXString(){}
CXString(const std::string &a):data(a){}
// forward needed functions needed.
// add functions
};

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
K

kanze

What's the relationship with the data? As other's have pointed
out, it is generally a bad idea to derive from std::string.
There are special cases, but the poster's doesn't seem to be one
of them.



What slicing problem? If he assigns his CXString to an
std::string, there will be slicing, but presumably, this isn't a
problem in his code.

What you can't do is delete an CXString through a std::string*.
In practice, I'm not sure that this is a problem -- I don't
think I've ever seen or heard of a case where a string was
allocated dynamically to begin with. As long as you don't do
this, there's no problem as far as the language goes. (Just
serious design problems.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

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
474,266
Messages
2,571,081
Members
48,772
Latest member
Backspace Studios

Latest Threads

Top