How can I add member functions in built-in classes in c++?

℡╲_俬逩灬. 提交于 2020-08-23 07:03:06

问题


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:

  1. inheritance
  2. composition
  3. 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 as charReplace(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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!