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

C++ 如何在c+;中的内置类中添加成员函数+;?,c++,string,member-functions,C++,String,Member Functions,我想在string类中添加一个新的成员函数“charReplace”。该函数将用另一个字符替换一个字符的所有出现。所以我准备了一个示例代码 #include <iostream> #include <string> std::string string::charReplace(char c1, char c2) { //error in this line while(this->find(c1) != std::string::npos) {

我想在string类中添加一个新的成员函数“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;
}
#包括
#包括
std::string string::charReplace(char c1,char c2){//此行出错
while(this->find(c1)!=std::string::npos){
int c1pos=this->find(c1);//查找c1的位置
此->替换(c1pos,1,c2);//将c1替换为c2
}
归还*这个;
}
int main(){
std::string s=“示例字符串”;
s、 charReplace('s','m')/*将所有s替换为m*/
std::cout您不能(也不应该)更改
std::string
类(特别是,因为它在C++11中是标准化的,并由其标准库提供)


你可以子类<代码> STD::String (但是这经常是皱眉)。

你不能。这是C++,不是JavaScript(在那里你可以对任何类进行原型化)。 你的选择是:

  • 继承权
  • 构图
  • 独立函数
  • 不能将函数“添加”到已定义的类中


    你可以做一个独立的函数,叫做“代码> CabExab[/Cuth>

    >P>”,除非你直接修改他们的定义(你不应该用标准类来做),否则没有办法在C++中对现有的类添加方法。 因此,您只能选择两个选项:

    • 子类化:对于标准库类,这是不鼓励的,除非你知道你在做什么。(如果你必须问,你可能不知道。例如,虚拟析构函数是这里的一个重点。)
    • 添加自由函数(或静态类函数):在您的例子中,这将是
      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
    的含义

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

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

    考虑到你的函数实现有一个严重的错误。如果参数
    c1
    c2
    指定了相同的字符,那么函数将有一个无限循环

    我将按照以下方式编写函数

    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;
    }
    
    但是我想用一个成员函数来实现它。那么,有没有办法呢 C++中的这个?< /P> 没有

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

    std::string
    已经足够膨胀了,以至于赫伯·萨特(Herb Sutter)曾经写过一篇关于它的文章

    在C++中,通过独立的、非朋友的函数来扩展类的功能是非常好的做法。这大大的<强>增强封装<强>,因为一个独立的、非朋友的函数不能访问<代码>私有< /代码>或<代码>保护< /COD>成员。 如果你看一下标准库或Boost库,你会发现这一原理被大量应用。整个“STL”(=容器/算法/迭代器)标准库的一部分是基于它的。容器类的公共接口,如
    std::set
    std::vector
    ,没有像
    reverse
    count\u if
    all\u of
    这样的函数。有一些独立函数:

    • 等等
    <>你应该遵循C++中的这个优秀的例子,不要反对它。


    std::string
    派生并向派生类添加成员函数在技术上是可行的。但这是糟糕的做法。下面是一个关于该主题的回答不错的问题,包括对著名专家Scott Meyers或Andrei Alexandrescu的书籍的参考:


    <>最后,注意到这种考虑不是C++独有的。例如,在java中,在爪哇中,最好从只被设计为基类的类中派生出来。这甚至是Joshua Bloch著名的“有效java”中的一个项目。在java的 String 类中,你甚至不能从它派生,当然,因为它是代码>最终< /代码>。如果C++ C++标准库是在今天设计的,那么在C++ 11中添加了新的特性,<>代码> STD::String < /C> >将是<代码>最终< /代码>。(尽管C++的发明家Bjarne Stroustrup显然从来没有成为最后一堂课的忠实粉丝,但这是另一个故事).

    但是这仍然不起作用,因为您不能/不应该编辑字符串标题。因此,在添加std::,之后,它仍然会抱怨函数,但现在它不是字符串的一部分。下面是一个更好的方法:字符串是一个相当复杂的结构(typedef basic_string string;)…我建议您定义一个包含字符串的新类,而新函数charReplaceyour
    replace
    是错误的-您的参数数量错误(请参阅),或者在(c==c1)的情况下为(char&c:s)使用
    std::replace
    :-)c= c2;继承是最坏的选择。大多数C++标准类不是继承的。列表中没有逻辑,但它至少暗示了(至少对我来说)这些都是同样好的解决方案。“例如,虚拟析构函数是这里的一个重要点”。-不,不是。从
    std::string
    派生已经够糟糕的了,添加一个虚拟析构函数会让事情变得更糟。也许你的意思是,当一个
    std::string
    没有虚拟析构函数时,尝试以多态方式删除它。这是真的
    mample mtring