Previously posted by jlou
Of course, the most important reason, in my opinion, is that string was not designed to be inherited from.
Originally written by Bjarne
Like other standard library types, a basic_string<T> is a concrete type without virtual functions. It can be used as a member when designing more sophisticated text manipulation classes, but it is not intended to be a base for derived classes.
Originally posted by Codeplug
Where does this say "don't inherit an object if it wasn't the programmers intention."?
Originally posted by jlou
First, who said that was the point of the quote?
"Not intended to be used polymorphicly" is allot different than "Not designed to be inherited from".
From The C++ Programming Language 3rd Edition by Bjarne Stroustrup
[5] Don't derive from a concrete class
This is just an OOP methology guideline. Inheritance is just one of several C++ language features that allow you to follow a particular OOP methology. If you want to attend the Church of Stroustrup, more power to you. I'm just not going to limit the use of a language feature simply because a particular OOP methology says [5].
On a side note, I attend the church of design patterns, although I don't go every Sunday (as I'm sure you can tell). It follows similiar guidelines as those in Stoned_Coder's post.
Originally posted by jlou
In fact, I use a class derived from basic_string here at my work. ... So an easy workaround to prevent the undefined behaviour might even be of specific use to me. So please share it.
I'm sure you'll be deleting that class via a basic_string pointer in your next project. And if you're truly worried about some morron doing that......then I feel your pain.
If, for whatever reason, you do want to use polymorphism, then provide a proper base class for your users. Here's what I mean:
Code:
#include <iostream>
#include <string>
using namespace std;
template<class _elem_t,
class _traits_t = char_traits<_elem_t>,
class _alloc_t = allocator<_elem_t> >
class poly_basic_string : public basic_string<_elem_t, _traits_t, _alloc_t>
{
public:
typedef _elem_t elem_t;
typedef _traits_t traits_t;
typedef _alloc_t alloc_t;
typedef poly_basic_string<elem_t, traits_t, alloc_t> my_t;
typedef basic_string<elem_t, traits_t, alloc_t> base_t;
// basic constructors
poly_basic_string(const elem_t *str) : base_t(str) {}
poly_basic_string(const base_t &str) : base_t(str) {}
// enforce virtual destruction
virtual ~poly_basic_string() {}
// assignment
base_t& operator=(const base_t& str) {return base_t::operator=(str);}
base_t& operator=(const elem_t *str) {return base_t::operator=(str);}
base_t& operator=(elem_t &e) {return base_t::operator=(e);}
// allow children to hook into c_str() calls
virtual const elem_t* c_str() const {return base_t::c_str();}
};//poly_basic_string
typedef poly_basic_string<char, char_traits<char>, allocator<char> >
poly_string;
typedef poly_basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >
poly_wstring;
class mystring : public poly_string
{
mutable int c_str_count;
public:
// basic constructors
mystring(const elem_t *str) : poly_string(str), c_str_count(0) {}
mystring(const base_t &str) : poly_string(str), c_str_count(0) {}
virtual ~mystring()
{
cout << "[mystring::c_str() called " << c_str_count << " times]" << endl;
}//destructor
// assignment
base_t& operator=(const base_t& str) {return base_t::operator=(str);}
base_t& operator=(const elem_t *str) {return base_t::operator=(str);}
base_t& operator=(elem_t &e) {return base_t::operator=(e);}
// count calls to c_str()
virtual const elem_t* c_str() const
{
c_str_count++;
return poly_string::c_str();
}//c_str
};//mystring
void print(const poly_string *str)
{
cout << str->c_str() << endl;
}//print
int main()
{
poly_string *str = new mystring("Hello World");
print(str);
*str = "Hello there ";
*str += "Enter some text: ";
print(str);
getline(cin, *str);
cout << "You entered: ";
print(str);
delete str;
return 0;
}//main
You could also use private or protected inheritance, or simply make the base class destructor virtual (making it non-concrete). Neither of these are helpful when extending basic_string and have their own set of pro's and con's.
gg