问题
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.
回答1:
you can't. this is C++, not JavaScript (where you can prototype any classes).
your options are:
- inheritance
- composition
- free standing functions
回答2:
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
回答3:
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;
}
回答4:
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).
回答5:
You cannot "add" a function to a already defined class.
What you can do is make a stand alone function, called charReplace
回答6:
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 ascharReplace(s,c1,c2)
. This is the only viable option here.
回答7:
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).
来源:https://stackoverflow.com/questions/31850978/how-can-i-add-member-functions-in-built-in-classes-in-c