I want to add a new member function "charReplace" to the string class. The function will replace all the occurances of one character with another character. So I prepared a sample code.
#include <iostream>
#include <string>
std::string string::charReplace(char c1, char c2) { //error in this line
while(this->find(c1) != std::string::npos) {
int c1pos = this->find(c1); //find the position of c1
this->replace(c1pos, 1, c2); //replace c1 with c2
}
return *this;
}
int main() {
std::string s = "sample string";
s.charReplace('s', 'm') /* replace all s with m */
std::cout << s << std::endl;
}
But it is not working. I am getting the following error in line 4 while compiling.
error: 'string' does not name a type
I know that it is quite easy to get the same result by creating a non-member function. But I want to do it using a member function. So, is there a way to do this in c++?
P.S. I am still new with c++. I have been using it for a few months only. So, please try to make your answer easy to understand.
you can't. this is C++, not JavaScript (where you can prototype any classes).
your options are:
inheritance
composition
free standing functions
You can't add to the std::string interface but you can do this:
#include <string>
#include <iostream>
#include <algorithm>
int main()
{
std::string s = "sample string";
std::replace(s.begin(), s.end(), 's', 'm'); /* replace all s with m */
std::cout << s << std::endl;
}
Output:
mample mtring
The error message points to this identifier
std::string string::charReplace(char c1, char c2) {
^^^^^^
that is unknown to the compiler. The compiler knows only std::string but it does not know what unqualified identifier string means.
But in any case the approach is incorrect because all members of a class shall be declared in the class definition. You may not to add new members of a class without changing its definition.
You can write a non-member function that will do the same task.
Take into account that your function implementation has a serious bug. If arguments c1 and c2 specify the same character then the function will have an infinite loop.
I would write the function the following way
std::string & charReplace( std::string &s, char c1, char c2 )
{
for ( std::string::size_type pos = 0;
( pos = s.find( c1, pos ) ) != std::string::npos;
++pos )
{
s[pos] = c2;
}
return s;
}
But I want to do it using a member function. So, is there a way to do
this in c++?
No.
However, the real question should be: Why?
std::string is bloated enough as it is. So much that Herb Sutter once wrote a GotW article about it.
In C++, it is very good practice to extend the functionality of a class through free-standing, non-friend functions. This greatly enhances encapsulation, because a free-standing, non-friend function cannot access private or protected members.
If you look at the standard library or the Boost libraries, you will find that this principle is applied a lot. The whole "STL" (= containers/algorithms/iterators) part of the standard library is based on it. The public interfaces of container classes like std::set or std::vector are not full of functions like reverse, count_if or all_of. There are free-standing functions for that:
http://en.cppreference.com/w/cpp/algorithm/reverse
http://en.cppreference.com/w/cpp/algorithm/count
http://en.cppreference.com/w/cpp/algorithm/all_any_none_of
etc...
You should follow this excellent example in C++, not work against it.
It is technically possible to derive from std::string and add member functions to the derived class. But this is bad practice. Here is a nice question with good answers on the topic, including references to books of renowned experts like Scott Meyers or Andrei Alexandrescu:
Why should one not derive from c++ std string class?
Finally, note that this kind of consideration is not unique to C++. Take Java, for example. In Java, it is best practice as well to derive only from classes which are designed to be base classes. This is even an item in Joshua Bloch's famous "Effective Java" book. In the case of Java's String class, you could not even derive from it, of course, because it is final. Chances are that if the C++ standard library was designed today, with the new features added in C++11, std::string would be final, too (even though Bjarne Stroustrup, the inventor of C++, has apparently never been a big fan of final classes, but this is another story).
You cannot (and you should not) change the std::string class (in particular, because it is standardized in C++11 and provided by its standard library).
You could subclass std::string (but this is often frown upon).
You cannot "add" a function to a already defined class.
What you can do is make a stand alone function, called charReplace
There is no way to do add methods to existing classes in C++, unless you directly modify their definition (which you are not supposed to do with standard classes).
Thus, you are limited to two options:
Subclassing: This is discouraged for standard library classes, unless you know what you are doing. (If you have to ask, you probably aren't. E.G. virtual destructors are an important point here.)
Adding free functions (or static class functions): In your case, that would be std::string charReplace(std::string& str, char c1, char c2){...};, called as charReplace(s,c1,c2). This is the only viable option here.
Related
I want to add a new member function "charReplace" to the string class. The function will replace all the occurances of one character with another character. So I prepared a sample code.
#include <iostream>
#include <string>
std::string string::charReplace(char c1, char c2) { //error in this line
while(this->find(c1) != std::string::npos) {
int c1pos = this->find(c1); //find the position of c1
this->replace(c1pos, 1, c2); //replace c1 with c2
}
return *this;
}
int main() {
std::string s = "sample string";
s.charReplace('s', 'm') /* replace all s with m */
std::cout << s << std::endl;
}
But it is not working. I am getting the following error in line 4 while compiling.
error: 'string' does not name a type
I know that it is quite easy to get the same result by creating a non-member function. But I want to do it using a member function. So, is there a way to do this in c++?
P.S. I am still new with c++. I have been using it for a few months only. So, please try to make your answer easy to understand.
you can't. this is C++, not JavaScript (where you can prototype any classes).
your options are:
inheritance
composition
free standing functions
You can't add to the std::string interface but you can do this:
#include <string>
#include <iostream>
#include <algorithm>
int main()
{
std::string s = "sample string";
std::replace(s.begin(), s.end(), 's', 'm'); /* replace all s with m */
std::cout << s << std::endl;
}
Output:
mample mtring
The error message points to this identifier
std::string string::charReplace(char c1, char c2) {
^^^^^^
that is unknown to the compiler. The compiler knows only std::string but it does not know what unqualified identifier string means.
But in any case the approach is incorrect because all members of a class shall be declared in the class definition. You may not to add new members of a class without changing its definition.
You can write a non-member function that will do the same task.
Take into account that your function implementation has a serious bug. If arguments c1 and c2 specify the same character then the function will have an infinite loop.
I would write the function the following way
std::string & charReplace( std::string &s, char c1, char c2 )
{
for ( std::string::size_type pos = 0;
( pos = s.find( c1, pos ) ) != std::string::npos;
++pos )
{
s[pos] = c2;
}
return s;
}
But I want to do it using a member function. So, is there a way to do
this in c++?
No.
However, the real question should be: Why?
std::string is bloated enough as it is. So much that Herb Sutter once wrote a GotW article about it.
In C++, it is very good practice to extend the functionality of a class through free-standing, non-friend functions. This greatly enhances encapsulation, because a free-standing, non-friend function cannot access private or protected members.
If you look at the standard library or the Boost libraries, you will find that this principle is applied a lot. The whole "STL" (= containers/algorithms/iterators) part of the standard library is based on it. The public interfaces of container classes like std::set or std::vector are not full of functions like reverse, count_if or all_of. There are free-standing functions for that:
http://en.cppreference.com/w/cpp/algorithm/reverse
http://en.cppreference.com/w/cpp/algorithm/count
http://en.cppreference.com/w/cpp/algorithm/all_any_none_of
etc...
You should follow this excellent example in C++, not work against it.
It is technically possible to derive from std::string and add member functions to the derived class. But this is bad practice. Here is a nice question with good answers on the topic, including references to books of renowned experts like Scott Meyers or Andrei Alexandrescu:
Why should one not derive from c++ std string class?
Finally, note that this kind of consideration is not unique to C++. Take Java, for example. In Java, it is best practice as well to derive only from classes which are designed to be base classes. This is even an item in Joshua Bloch's famous "Effective Java" book. In the case of Java's String class, you could not even derive from it, of course, because it is final. Chances are that if the C++ standard library was designed today, with the new features added in C++11, std::string would be final, too (even though Bjarne Stroustrup, the inventor of C++, has apparently never been a big fan of final classes, but this is another story).
You cannot (and you should not) change the std::string class (in particular, because it is standardized in C++11 and provided by its standard library).
You could subclass std::string (but this is often frown upon).
You cannot "add" a function to a already defined class.
What you can do is make a stand alone function, called charReplace
There is no way to do add methods to existing classes in C++, unless you directly modify their definition (which you are not supposed to do with standard classes).
Thus, you are limited to two options:
Subclassing: This is discouraged for standard library classes, unless you know what you are doing. (If you have to ask, you probably aren't. E.G. virtual destructors are an important point here.)
Adding free functions (or static class functions): In your case, that would be std::string charReplace(std::string& str, char c1, char c2){...};, called as charReplace(s,c1,c2). This is the only viable option here.
I just miss some functions in the c++ standard library string class, so I just wanted to add these by myself. I wrote this:
#include <string>
class String : public std::string
{
public:
// some new fancy functions
};
and later noticed by reading some forums, that it is a bad idea to inherit from std::string and any other container from the standard library.
I just want the normal string, but with additional functions written by myself, how can I achieve this in the right way? Or is there no way to do it right and I have to right my own string class?
tl;dr: Use freestanding functions.
First of all - std::string is kind of a mess, and has too many methods as-is. It's bad design to lump functionality into a class which doesn't need to be in that class, and can easily be implemented using simpler, more basic class methods - as a freestanding function.
Moreover - std::string is at the same time unwieldy to manipulate (it's not a string buffer or an std::stringstream), and not impossible to manipulate, i.e. not immutable.
But coming back to my earlier point: The "right way" - if there is any - to do what you wanted is with freestanding functions. For example, suppose you want to randomly permute the contents of an std::string. Well, either:
std::string& jumble(std::string& str)
or
std::string jumble(std::string str)
or maybe, if you want to feel cool and micro-optimized,
std::string jumble(const std::string& str)
std::string jumble(std::string&& str)
depending if you want to use strings more as immutable or as mutable entities.
Also remember, that we don't really have a single std::string class - we have a template based on the character type (and an allocator etc.), so if you want to be generic, you have to accept this class:
template<
class CharT,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>
> class basic_string;
PS - If we had uniform call syntax, like Bjarne proposed - which we really should IMHO - your freestanding functions could simply be invoked as though they were members:
auto jumbled = my_string.jumble();
std::string (as most — if not all — standard classes) doesn’t have any virtual methods, so creating an inherited class with virtual methods will result in UB (due most likely to the destructor). (correct me if I am wrong).
I thought that inheriting without polymorphism it’s ok though, until I read upon the net on this subject.
For instance, in this answer: Why should one not derive from c++ std string class? some arguments are given against this practice. The main reason seems to be the slicing problem which will inhibit the added functionality when the derived object is passed to a function in place of a std::string parameter, thus making the non-polymorphism not logical. The idiomatic C++ way is to create free functions if one wants to extend the functionality of string. And I agree with all that, especially since I am an advocate for free functions instead of monolithic classes.
That being said I think that I found a situation that I think actually warrants the non-polymorphic inheritance from std::string. I will first show what issue I am trying to solve, then I will show the reasons why I think inheriting from std::string is the best solution here.
When porting a function used for debugging purposes from C to C++ I realised there is no way to create formatted strings in C++ (not using C-like string functions e.g. sprintf). I.e.:
C version: void someKindOfError(const char *format, ...);
this would be called like:
someKindOfError("invalid argument %d, size = %d", i, size);
C++ version: void someKindOfError(const std::string &message);
to call this to a similar effect would be:
std::stringstream ss;
ss << "invalid argument " << i << ", size = " << size;
someKindOfError(ss.str());
this can’t be a one liner because the << operator returns an ostream. So this requires 2 extra lines and an extra variable.
The solution I came up with is a class called StreamString that inherits from std::string (actually a templated BasicStreamString that inherits from basic_string<>, but that’t not important) and as far as the new functionality goes it has the operator << that mimics the behaviour of the stringstream operator and conversion to and from string.
So the previous example can become:
someKindOfError(StreamString() << "invalid argument " << i << ", size = " << size);
remember that the parameter type is still const std::string &
The class is created and fully functional. And I found this class very useful in a lot of places when a string is need to be created ad-hoc, without the extra burden of having to declare an extra stringstream variable. And this object can be manipulated further like a stringstream, but it is actually a string and can be passed to functions expecting string.
Why I think this is an exception to the C++ idiom:
the object needs to behave exactly like a string when passed to functions expecting a string, so the slicing problem is not an issue.
the only (noteworthy) added functionality is the operator << which I am reluctant to overload as a free function for a standard string object (this would be done in a library).
One alternative I can think of is to create a variadic templated free function. Something like:
template <class... Args>
std::string createString(Args... args);
which allow us to call like this:
someKindOfError(createString("invalid argument ", i , ", size = " , size));
One disadvantage of this alternative is the lost of the ability to easily manipulate the string like an stringstream after it’s creation. But I suppose I can create a free function to handle that too. Also people are use with the operator << to perform formatted inserts.
To round up:
Is my solution bad practice (or worst) or it is an exception to the C++ idiom and it is OK?
If it is bad, what viable alternatives are there? Is createString ok? Can it be improved?
You don't need to derive a class from std::string for this. Just create an unrelated class, say StringBuilder that keeps a std::stringstream internally. Overload operator << for this class and add a std::string cast operator.
Something like this should do the trick (untested):
class StringBuilder
{
std::ostringstream oss;
public:
operator std::string() const
{
return oss.str();
}
template <class T>
friend StringBuilder& operator <<(StringBuilder& sb, const T& t)
{
sb.oss << t;
return *this;
}
};
Your StreamString class is OK, in that there do not seem to be any situations where normal usage of it could get you into trouble. Even so, there are a lot of alternatives that might be more appropriate to this situation.
Use a pre-existing library, such as Boost.Format, rather than rolling your own. This has the advantage of being widely known, tested, supported, etc...
Write someKindOfError to be a variadic template, to match the C version, but with added C++ type-safety goodness. This has the advantage of matching the C version, and so being familiar to your existing users.
Give StringStream a conversion operator or an explicit to_string function, rather than inheriting from std::string. This gives you more flexibility to change the implementation of the StringStream at a later stage. (For example, at a later stage, you might decide that you want to use some kind of cacheing or buffering scheme, but this would be impossible if you do not know exactly when the final string will be extracted from the StringStream).
As it is, your design is conceptually flawed. The only thing that you need is the ability to convert a StringStream to a std::string. Inheritance is an overly heavy-handed way of achieving that goal, when compared to using a conversion operator.
Write your original stringstream code as a one-liner:
someKindOfError(static_cast<std::stringstream &>(
std::stringstream{} << "invalid argument " << i << ", size = " << size).str());
... well, that's pretty ugly, so maybe not. You should consider it though, if your only reason for not doing this was that you thought it was not possible.
I have read about pointers to class members, but I have never seen them being used in any practical applications. Can someone explain what are the use cases of such pointers? Is it really necessary to have such pointers?
Eg.
class abc
{
public:
int a;
abc(int val) { a = val; }
};
int main()
{
int abc::*data;
abc obj(5);
data = &abc::a;
cout << "Value of a is " << obj.*data << endl;
return 0;
}
In the above eg. why is the value of 'a' accessed in this manner? What is the advantage of using pointers to class members?
The biggest advantage of a pointer-to-member or pointer-to-member-function is that you
don't have to bind to a specific instance right away
don't need to place any restrictions on the member names, only the type has to match.
This can be used for e.g. call-backs or abstract algorithms:
std::map<int,int> m;
m.insert(std::make_pair(1,2));
m.insert(std::make_pair(3,4));
m.insert(std::make_pair(5,6));
std::ptrdiff_t s =
std::count_if(m.begin(), m.end(),
boost::bind(&std::map<int,int>::value_type::first, _1) > 2);
std::cout << s << std::endl; // 2
Note that Boost.Bind, Boost.Function and their TR1 equivalents already encapsulate that nicely for you. To a certain degree the current standard also includes tools like std::mem_fun in <functional>.
If you have used MFC, you will see pointers to member function concept is heavily used (internally)
DECLARE_MESSAGE_MAP, BEGIN_MESSAGE_MAP, END_MESSAGE_MAP
See Message Maps
The question I suppose is: "what does pointer to member data add over simple pointer to data?" and the only answer I can think of is a level of explicit meaning: we are pointing at data in this class.
Now I can see some value in what is effectively some additional documentation of intent. One example I've seen that might be quite powerful is when our "class" is actually a legacy C struct. Now we have no local methods of that struct, so having some pointers that are explicitly associated with that struct may well make our code clearer.
Pointer-to-member is, like all C++ features, just syntactic sugar for something you could already have done in pure C.
Pointers-to-member-variable are pretty simple. One use case is if you wanted to write a (template) function that could sort an array of structures by any field. By passing in a pointer-to-member, you can retrieve some specified field of any instance of the structure without having to hard-code the field. Of course a functor that accepts a structure pointer and returns the field value could have been used instead.
Pointers-to-member-function are a little more complicated. At first glance, they are just like ordinary function pointers that know how to pass the hidden 'this' pointer. But virtual functions make a simple idea pretty complicated.
And virtual base classes make all pointers-to-member awfully complicated. It's not something you'd want to code yourself using simple C constructs. But the complex cases are rare.
I just don't get it. Tried on VC++ 2008 and G++ 4.3.2
#include <map>
class A : public std::multimap<int, bool>
{
public:
size_type erase(int k, bool v)
{
return erase(k); // <- this fails; had to change to __super::erase(k)
}
};
int main()
{
A a;
a.erase(0, false);
a.erase(0); // <- fails. can't find base class' function?!
return 0;
}
When you declare a function in a class with the same name but different signature from a superclass, then the name resolution rules state that the compiler should stop looking for the function you are trying to call once it finds the first match. After finding the function by name, then it applies the overload resolution rules.
So what is happening is the compiler finds your implementation of erase(int, bool) when you call erase(0), and then decides that the arguments don't match.
1: You need to be extremely careful when deriving from C++ standard library containers. It can be done, but because they don't have virtual destructors and other such niceties, it is usually the wrong approach.
2: Overload rules are a bit quirky here. The compiler first looks in the derived class, and if it finds any overload with the same name, it stops looking there. It only looks in the base class if no overloads were found in the derived class.
A simple solution to that is to introduce the functions you need from the base class into the derived class' namespace:
class A : public std::multimap<int, bool>
{
public:
using std::multimap<int, bool>::erase; // Any erase function found in the base class should be injected into the derived class namespace as well
size_type erase(int k, bool v)
{
return erase(k);
}
};
Alternatively, of course, you could simply write a small helper function in the derived class redirecting to the base class function
You've hidden the base class's erase member function by defining a function in the derived class with the same name but different arguments.
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9
First of all, you should never derive from STL containers, because no STL containers define a virtual destructor.
Second of all, see Greg's answer about inheritance.
Think whether you really want to inherit from std::map. In all the time I've written code, and that's longer than STL exists, I've never seen an instance where inheriting from a std::container was the best solution.
Specifically, ask yourself whether your class IS a multimap or HAS a multimap.
Others have answered how to resolve the syntax problem and why it can be dangerous to derive from standard classes, but it's also worth pointing out:
Prefer composition to inheritance.
I doubt you mean for 'A' to explicitly have the "is-a" relationship to multimap< int, bool >. C++ Coding Standards by Sutter/Alexandrescu has entire chapter on this (#34), and Google points to many good references on the subject.
It appears there is a SO thread on the topic as well.
For those that use Effective C++ as a C++ programming reference, this issue is covered in Item 33 (Avoid hiding inherited names.) in the book.
I agree with others' comments that you need to be very careful inheriting from STL classes, and it should almost always be avoided.
However, this problem could arise with some other base class from which it's perfectly sensible to inherit.
My question is: why not give your 2-argument function a different name? If it takes different arguments, presumably it has a slightly different meaning? E.g. erase_if_true or erase_and_delete or whatever the bool means.
To replace __super in a portable way, define a typedef at the top of your class like this:
typedef std::multimap<int, bool> parent;
public:
size_type erase(int k, bool v)
{
return parent::erase(k);
}
It does not need to be "parent" of course. It could be any name you like, as long as it is used consistently throughout your project.