如何在 C++ 的内置 类 中添加成员函数?

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

我想给字符串class添加一个新的成员函数"charReplace"。该函数将用另一个字符替换一个字符的所有出现。所以我准备了一个示例代码。

#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;
}

但它不起作用。我在编译时在第 4 行收到以下错误。

error: 'string' does not name a type

我知道通过创建非成员函数很容易得到相同的结果。但我想使用成员函数来完成。那么,有没有办法在 C++ 中做到这一点?

P.S。我还是 c++ 的新手。我只使用了几个月。所以,请尽量让你的回答通俗易懂。

您不能(也不应该)更改 std::string class(特别是因为它已在 C++11 中标准化并由其标准库提供)。

你可以subclass std::string(但这通常不受欢迎)。

你不能。这是 C++,而不是 JavaScript(您可以在其中制作任何 类 的原型)。

您的选择是:

  1. 继承
  2. 作文
  3. 独立函数

您不能 "add" 已定义的函数 class。

你可以做一个独立的函数,叫做 charReplace

无法在 C++ 中向现有 classes 添加方法,除非您直接修改它们的定义(您不应该对标准 classes 执行此操作)。

因此,您只有两种选择:

  • Subclassing:标准库 classes 不鼓励这样做,除非你知道自己在做什么。 (如果你不得不问,你可能不是。例如,虚拟析构函数在这里很重要。)
  • 添加自由函数(或静态 class 函数):在您的情况下,这将是 std::string charReplace(std::string& str, char c1, char c2){...};,称为 charReplace(s,c1,c2)。这是这里唯一可行的选择。

错误信息指向这个标识符

std::string string::charReplace(char c1, char c2) { 
            ^^^^^^

编译器不知道。编译器只知道 std::string 但不知道非限定标识符 string 是什么意思。

但无论如何这种方法都是不正确的,因为 class 的所有成员都应在 class 定义中声明。在不更改其定义的情况下,您不得添加 class 的新成员。

您可以编写一个非成员函数来完成相同的任务。

考虑到您的函数实现存在严重错误。如果参数 c1c2 指定相同的字符,那么该函数将有一个无限循环。

我会这样写函数

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;
}

您无法添加到 std::string 界面,但您可以这样做:

#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;
}

输出:

mample mtring

But I want to do it using a member function. So, is there a way to do this in c++?

没有

然而,真正的问题应该是:为什么?

std::string 已经够臃肿了。以至于 Herb Sutter 曾经写过一篇关于它的 GotW article

在 C++ 中,通过独立的非友元函数扩展 class 的功能是一个很好的做法。这极大地 增强了封装性 ,因为独立的非友元函数无法访问 privateprotected 成员。

如果你看一下标准库或者Boost库,你会发现这个原则应用的很多。标准库的整个 "STL" (= containers/algorithms/iterators) 部分都是基于它的。像std::setstd::vector这样的容器class的public接口并不像reversecount_ifall_of那样具有完整的功能.有独立的功能:

你应该在 C++ 中遵循这个优秀的例子,而不是反对它。


技术上 可以从 std::string 派生并向派生的 class 添加成员函数。但这是不好的做法。这是一个很好的问题,在这个主题上有很好的答案,包括对 Scott Meyers 或 Andrei Alexandrescu 等知名专家书籍的引用:

Why should one not derive from c++ std string class?

最后请注意,这种考虑并不是C++独有的。以Java为例。在 Java 中,最好的做法是从 classes 中派生出 only,这些 classes 被设计为基础 classes。这甚至是 Joshua Bloch 著名的 "Effective Java" 书中的一个项目。在 Java 的 String class 的情况下,你甚至无法从中推导出来,当然,因为它是 final。很有可能,如果 C++ 标准库是今天设计的,随着 C++11 中添加的新功能,std::string 也将是 final(尽管 C++ 的发明者 Bjarne Stroustrup 显然已经从来都不是 final classes 的忠实粉丝,但这是另一回事了)。