编写strcpy函数和类String的构造函数、析构函数、赋值函数和重载运算符函数
- 格式:docx
- 大小:19.54 KB
- 文档页数:7
(0166)《面向对象技术》复习思考题一、选择题1、以下说法中正确的是( )A.C++程序总是从第一个定义的函数开始执行B.C++程序总是从main函数开始执行C.C++函数必须有返回值,否则不能使用函数D.C++程序中有调用关系的所有函数必须放在同一个程序文件中2、一个函数功能不太复杂,但要求被频繁调用,选用()A.内联函数 B.重载函数C.递归函数 D.嵌套函数3、构造函数不具备的特征是 ( )A.构造函数的函数名与类名相同B.构造函数可以重载C.构造函数可以设置默认参数D.构造函数必须指定类型说明4、下列不是描述类的成员函数的是()A. 友元函数 B.析构函数C.构造函数 D.拷贝构造函数5、int Func(int,int);不可与下列哪个函数构成重载()A.int Func(int,int,int); B.double Func(int,int);C.double Func(double,double);D.double Func(int,double);6、一个类可包含析构函数的个数是()A.0个 B.1个C.至少一个D.0个或多个7、在编译指令中,宏定义使用哪个指令()A.#include B.#defineC.#if D.#else8、在关键字public后面定义的成员为类的( )A.私有成员B. 保护成员C. 公有成员D.任何成员9、下列关于指针的运算中,( )是非法的。
A.两个指针在一定条件下,可以进行相等或不等的运算;B.可以用一个空指针赋值给某个指针;C.一个指针可以加上两个整数之差;D.两个指针在一定条件下,可以相加。
10、在C++中,关于下列设置缺省参数值的描述中,正确的是( )。
A. 不允许设置缺省参数值;B. 在指定了缺省值的参数右边,不能出现没有指定缺省值的参数;C. 只能在函数的定义中指定参数的缺省值;D. 设置缺省参数值时,必须全部都设置。
11、预处理命令在程序中是以( )开头的。
创维笔试秘籍1.1 笔试概述创维集团的招聘笔试针对不同类型的岗位会有不同的题目。
例如技术类的岗位会考查相关专业知识的内容,而营销类的岗位则偏向考查思维能力、逻辑推理能力等内容。
1.2 笔试真题创维技术类面试笔试题一、填空1. 二极管有 1 个PN结,三极管有 2 个PN结。
2 流过电感元件两端的电流发生变化时,会在电感元件两端产生感应电压。
3 基本放大电路根据其信号输入输出的接法不同,有共射组态、共集组态度、共基组态三种组态之分,这三种组态是最基本的放大单元电路。
4 描述正弦交流信号U(s)=Asin(ωt+φ)的三种物理量A、ω、φ含义分别是、、5 正弦波震荡电路是由放大电路和选频网络组成的。
6 二进制数11010用十进制数表示为26 ;十进制数18用二进制数表示为10010二进制数1101+1001= 10110 (用二进制数表示)7 电容的国际单位为法拉力(中/英文), 3.3×104PF= UF= F8 理想化集成运算放大器的两个特性是、,该特性也是分析理想化运放电路的基本原则。
9 三极管从放大机理上来说是放大信号的(电流/电压?)10. 三极管的三种工作状态为、、.二、问答1.请简述调制的作用及方式,与调制相对应的方式是什么?2 .请画出二极管、三极管(PNP、NPN型各一个)、晶闸管的电路符号图。
分别说明各自的用途有哪些?3.分析说明下面的二极管检波电路的检波原理,说出二极管、电容、电阻的各自作用,画出U2的大致波形。
三、计算题(要求写出计算步骤,直接写结果不计分)1、如下图之电路,求电流I1和I2的大小(提示:根据基尔霍夫电流定律)要求:写出基尔霍夫求职胜经/简历亮出你的精彩简历写作技巧,...面试前准备才是...电流定律的基本内容.A2、下图中二极管为理想二极管(不考虑导通压降与内阻),计算,当电源电压分别为+10V 和-10V时流过R1的电流是多少?3.请计算下列的等值阻值或电容值.四翻译1、I go to school on foot everyday.2、I am looking for work,so I must study try my best everyday.创维营销笔试题它涉及的内容没有营销专业方面的题目,而是其他的。
含有指针变量的类需要重写拷贝构造函数,拷贝赋值函数,析构函数编译器⾃带拷贝构造(ctor)和拷贝赋值函数(operator =),但是对于成员变量含有指针的类,其不能使⽤默认的拷贝赋值函数。
因为使⽤默认的,会直接将指针指向的地址进⾏赋值 (浅拷贝,共享内存,共指⼀个对象),⽽不是分配⼀块内存,具有相同的数值 (深拷贝,独⽴,两个对象)。
浅拷贝容易造成dangling pointer。
⽤⼀个例⼦来展⽰:1 #ifndef __MYSTRING__2#define __MYSTRING__34class String{5public:6 String(const char* cstr=0);7 String(const String& str); // 拷贝构造8 String& operator= (const String& str); // 拷贝赋值9 ~String();10char* get_c_str const(){11return m_data;12 }13private:14char* m_data; // 带指针成员的类:⼀定要注意拷贝赋值,拷贝构造,析构15// String的底部通过char实现,在外部表现为string16 };1718 inline String::String ( const char* cstr=0 ){19if(cstr){20 m_data=new char[strlen(cstr)+1];21 strcpy(m_data,cstr); // char * strcpy ( char * destination, const char * source );22 }23else{ // 考虑cstr=0;24 m_data=new char[1];25 m_data[0]='\0';26 }27 }2829 inline String::String(const String& str){30 m_data=new char[strlen(str.get_c_str())+1];31 strcpy(m_data,str.m_data);32 }3334 inline String::~String(){35delete[] m_data;36 }3738 inline String& String::operator=(const String& str){39if(this==&str){ // self assignment :⾃我检验(如果没有进⾏这样的处理,在⾃我赋值会产⽣严重的错误)40return *this;41 }42// 构造函数是第⼀次,因此不需要删除,但是赋值需要先进⾏delete43delete[] m_data; // 先删除,重新分配⼀样⼤⼩!44 m_data=new char[strlen(str.get_c_str())+1];45 strcpy(m_data,str.m_data);46return *this; // 其实不⽤返回*this也可以,因为已经实现了修改,但是这样有⼀个好处可以实现 a=b=c;(因为返回的类型继续⽀持=)47 }4849// 调⽤形式: cout << String() ; 第⼀个参数为 << 左边,第⼆个参数为 << 右侧;返回ostream 可以实现 cout << a << b ;50 ostream& operator<<(ostream& os,const String& str){51 os<<str.get_c_str();52return os;53 }5455#endif。
湖南大学课程考试试卷考试中心填写:C. 使用作用域分辨操作符或虚基类D. 使用虚基类或赋值兼容规则10.如果在类CTest的外面函数调用CTest::f();则函数f()是类CTest的( A )。
A. 静态成员函数B. 非静态成员函数C. 友元函数D. 前面都不正确析:友元函数不输入类成员,故不能那样调用。
11.对虚基类的定义,( B )。
A. 不一定要使用虚函数B. 必须使用虚函数C. 必须使用privateD. 必须使用public12.假定CTest为一个类,并且构造函数的参数无缺省值,则执行CTest objTest语句时将自动调用该类的( A )。
A. 有参构造函数B. 无参构造函数C. 拷贝构造函数D. 赋值重载函数析:无缺省值既有默认值,例如A(int i=0,double=”hello”).13.当一个类的某个函数被说明为virtual时,该函数在该类的所有派生类中( A )。
A. 都是虚函数B. 只有被重新说明时才是虚函数C. 只有被重新说明为vittual时才是虚函数D. 都不是虚函数析:之后,派生类的该虚函数前的virtual关键字可加可不加14.调用一个成员函数时,使用动态联编的情况是( B )。
A. 通过对象调用一虚函数B. 通过指针或引用调用一虚函数C. 通过对象调用一静态函数D. 通过指针或引用调用一静态函数析:记住,通过对象调用虚函数不会出现多态(通过指针或者引用才会有多态性)在构造函数里面调用虚函数不会出现多态指定命名域调用不会出现多态15.在派生类中能够直接访问基类的( D )。
A. 公有成员和私有成员B. 保护成员和私有成员C. 不可访问的和私有的成员D. 保护成员和公有成员二、判断正误题(本大题共10小题,每小题1分,共10分)判断正误,在题后的括号内,正确的划上“√”错误的划上“×”。
1.friend属于类的存取权限。
(√)2.重载函数要求函数有相同的函数名,但具有不同的参数个数或参数类型。
详解C++中构造函数,拷贝构造函数和赋值函数的区别和实现C++中⼀般创建对象,拷贝或赋值的⽅式有构造函数,拷贝构造函数,赋值函数这三种⽅法。
下⾯就详细⽐较下三者之间的区别以及它们的具体实现1.构造函数构造函数是⼀种特殊的类成员函数,是当创建⼀个类的对象时,它被调⽤来对类的数据成员进⾏初始化和分配内存。
(构造函数的命名必须和类名完全相同)⾸先说⼀下⼀个C++的空类,编译器会加⼊哪些默认的成员函数默认构造函数和拷贝构造函数析构函数赋值函数(赋值运算符)取值函数**即使程序没定义任何成员,编译器也会插⼊以上的函数!注意:构造函数可以被重载,可以多个,可以带参数;析构函数只有⼀个,不能被重载,不带参数⽽默认构造函数没有参数,它什么也不做。
当没有重载⽆参构造函数时,A a就是通过默认构造函数来创建⼀个对象下⾯代码为构造函数重载的实现<span style="font-size:14px;">class A{int m_i;Public:A(){Cout<<”⽆参构造函数”<<endl;}A(int i):m_i(i) {} //初始化列表}</span>2.拷贝构造函数拷贝构造函数是C++独有的,它是⼀种特殊的构造函数,⽤基于同⼀类的⼀个对象构造和初始化另⼀个对象。
当没有重载拷贝构造函数时,通过默认拷贝构造函数来创建⼀个对象A a;A b(a);A b=a; 都是拷贝构造函数来创建对象b强调:这⾥b对象是不存在的,是⽤a 对象来构造和初始化b的!!先说下什么时候拷贝构造函数会被调⽤:在C++中,3种对象需要复制,此时拷贝构造函数会被调⽤1. 1)⼀个对象以值传递的⽅式传⼊函数体2. 2)⼀个对象以值传递的⽅式从函数返回3. 3)⼀个对象需要通过另⼀个对象进⾏初始化什么时候编译器会⽣成默认的拷贝构造函数:1. 1)如果⽤户没有⾃定义拷贝构造函数,并且在代码中使⽤到了拷贝构造函数,编译器就会⽣成默认的拷贝构造函数。
c++ string类的常用方法一、C++ string类的常用方法1、string类的构造函数string() // 构造空串string(const char* s) // 把null结尾的字符串s拷贝到字符串中string(const string& str) // 拷贝构造函数,复制str到此串string(char c, int n) // 用n个字符c构造串string(const char* s, int n) // 拷贝字符数组中前n个字符2、string类的成员函数2.1 长度控制函数int size() const; // 返回字符串的长度int length() const; // 返回字符串的长度,等价于size()void resize(int n, char c); // 改变字符串长度,如果n 大于原来的长度,用字符c来填充2.2 内容操作函数string& operator=(const char* s); // 赋值,把s的内容复制到字符串中string& assign(const char* s); // 赋值,把s的内容复制到字符串中string& append(const char* s); // 把字符串s添加到串尾string& append(const char* s, int n); // 把s前n个字符添加到串尾string& insert(int p0, const char* s); // 在p0位置上插入字符串sstring& erase(int p0, int n); // 删除p0开始,n个字符int find(const char* s, int pos=0); // 在pos之后查找子串s,返回子串s在原串中的起始位置int find(char c, int pos=0); // 从pos开始查找字符c,返回字符c在原串中的位置int rfind(const char* substr,int pos=npos); // 从pos开始向前查找子串substr,返回子串substr在原串中的起始位置int rfind(char c, int pos=npos); // 从pos开始向前查找字符c,返回字符c在原串中的位置string substr(int pos, int n); // 返回串pos 位置开始,长度为n的子串2.3 字符串比较函数int compare(const char* s); // 比较原串和sint compare(int p0, int n, const char* s); // 比较串中p0开始,n个字符的子串和s2.4 数据访问函数char& operator[](int i); // 返回串中第i个字符的引用const char& operator[](int i) const; // 返回串中第i个字符的引用const char* c_str() const; // 返回字符串以null结尾的字符串2.5 输入输出函数ostream& operator<<(ostream& os, const string& str); // 输出字符串istream& operator>>(istream& is, string& str); // 输入字符串。
郑州轻工业学院 2009/2010学年 第1学期《C++》试题A1.下列运算符种,( )运算符在C++中不能重载。
A )>> B )[ ] C )? : D )&& 2.C++源程序文件的扩展名为( )。
A ).EXEB ).C C ).DLLD ).CPP3.下列关于动态联编的描述中,错误的是( )。
A )动态联编是以虚函数为基础的B )动态联编是在运行时确定所调用的函数代码的C )动态联编调用函数操作是指向对象的指针或对象引用D )动态联编是在编译时确定操作函数的4.下面的函数声明中, 哪一个是" void BC(int a, int b );"的重载函数( )。
A )int BC(int x, int y ); B )void BC(int a, char b );C )float BC(int a, int b, int c=0);D )int BC(int a, int b = 0);5.对类的构造函数和析构函数描述正确的是( )。
A )构造函数可以重载,析构函数不能重载 B )构造函数不能重载,析构函数可以重载 C )构造函数可以重载,析构函数也能重载 D )构造函数不能重载,析构函数也不能重载6.C++中类有两种用法:一种是类的实例化,即生成类的对象,并参与系统的运行;另一种是通过( )派生出的新类。
A )复用B )继承C ) 封装D )引用 7.在下面的4个选项中,( )是用来声明虚函数的。
A )virtual B )public C )using D )false 8.下面对于友元函数的描述是正确的是( )。
A )友元函数的实现必须在类的内部定义 B )友元函数是类的成员函数C )友元函数破坏了类的封装性和隐藏性D )友元函数不能是访问类的私有成员9.假定MyClass 为一个类,则该类的拷贝初始化构造函数的声明语句是( )。
C++在单继承、多继承、虚继承时,构造函数、复制构造函数、赋值操作符、析构函数的执⾏顺序和执⾏内容⼀、本⽂⽬的与说明1. 本⽂⽬的:理清在各种继承时,构造函数、复制构造函数、赋值操作符、析构函数的执⾏顺序和执⾏内容。
2. 说明:虽然复制构造函数属于构造函数的⼀种,有共同的地⽅,但是也具有⼀定的特殊性,所以在总结它的性质时将它单独列出来了。
3. 单继承、多继承、虚继承,既然都属于继承,那么虽然有⼀定的区别,但还是相同点⽐较多。
如果放在⼀块讲,但为了将内容制作成递进的,就分开了,对相同点进⾏重复,(⼤量的复制粘贴哈),但在不同点进⾏了标注。
注意:三块内容是逐步递进的如果你懂虚函数,那么单继承和多继承那块你就可以不看;如果你懂多继承,那单继承你就不要看了,⾄于虚继承就等你懂虚继承再回来看吧;如果你只懂单继承,那你就只看单继承就好。
⼆、基本知识1. 对于⼀个空类,例如:class EmptyClass{};虽然你没有声明任何函数,但是编译器会⾃动为你提供上⾯这四个⽅法。
class EmptyClass {public:EmptyClass(); // 默认构造函数EmptyClass(const EmptyClass &rhs); // 复制构造函数~EmptyClass(); // 析构函数EmptyClass& operator=(const EmptyClass &rhs); // 赋值运算符}对于这四个⽅法的任何⼀个,你的类如果没有声明,那么编译器就会⾃动为你对应的提供⼀个默认的(注意合成默认构造函数是⽤于没有编写构造函数编译器才会合成默认构造函数,其中复制构造函数也是构造函数)。
(在《C++ primer》中,这个编译器⾃动提供的版本叫做“合成的***”,例如合成的复制构造函数)当然如果你显式声明了,编译器就不会再提供相应的⽅法。
2. 合成的默认构造函数执⾏内容:如果有⽗类,就先调⽤⽗类的默认构造函数。
姓名:___________ 时间:___________DCCBB AADAD一、选择题(1*10=10)1.如果派生类以proctected方式继承基类,则原基类的protected和public 成员在派生类的访问性分别是:DA.public和public B.public和protected C.protected和public D.protected和protected解析:通过protected方式继承基类后,原基类的私有成员不可访问,而protected和public成员均变成protected成员。
答案:D2.有如下头文件:int F1();static int F2();classs CA{public:int F3();static int F4();};在所描述的函数中,具有隐含this指针的是:CA.F1 B.F2C.F3 D.F4本题考查的是this指针。
this指针式一个隐含的指针,它隐含于每个类的非静态成员函数中,它明确地表示出了成员函数当前操作的数据所属的对象。
当对一个对象调用成员函数时,编译程序先将对象的地址赋值给this指针,然后调用成员函数,每次成员函数存取数据成员时,则隐含使用this指针。
this指针是指向对象本身的指针,它只存在于类的非静态成员中。
f1,f2不是成员函数,不存在隐含指针;f4为静态成员函数,也不含有this指针;含有this指针的函数在调用时按thiscall调用约定调用。
故本题答案为C。
3.派生类的成员函数不能访问基类的:CA.共有成员和保护成员B.共有成员C.私有成员D.保护成员本题考查的是继承的类型。
类的继承方式有公有继承、保护继承和私有继承三种方式。
对于公有继承基类中的成员访问属性不变,对于保护和私有继承基类中的成员转换为相应的访问类型。
但是如果基类成员的访问属性为private的,则不能被继承。
故本题答案为C。
4.按照“后进先出”原则组织数据的数据结构是BA.队列B.栈C.双向链表D.二叉树答案为B。
c++ string类的常用方法x1、string类的构造函数string类的构造函数有三种:(1)默认构造函数:string();(2)以字符串常量指针为参数的构造函数:string (const char *s);(3)以字符串对象为参数的构造函数:string (const string &str);2、string类的赋值操作string类的赋值操作有以下几种:(1)以字符串常量指针为参数的赋值运算符重载:string & operator = (const char *s);(2)以字符串对象为参数的赋值运算符重载:string & operator = (const string &str);(3)拼接函数:string &append (const string &str);(4)两个字符串的拼接:string + string;3、string类的比较操作string类的比较操作有如下几种:(1)比较两个字符串是否相等的比较操作符:string==string;(2)比较两个字符串是否不等的比较操作符:string!=string;(3)比较两个字符串大小的比较操作符:string>string;4、string类的查找操作string类的查找操作有以下几种:(1)查找从某个位置开始某个子串的位置的函数:size_tfind(const string &str,size_t pos = 0);(2)查找从某个位置开始某个字符的位置的函数:size_tfind(char c,size_t pos = 0);(3)查找从右向左某个子串的位置的函数:size_t rfind(const string &str,size_t pos = string::npos);(4)查找从右向左某个字符的位置的函数:size_t rfind(char c,size_t pos = string::npos);5、string类的修改操作string类的修改操作有以下几种:(1)插入字符串的函数:string &insert (size_t pos, const string &str);(2)替换某个子串的函数:string &replace (size_t pos, size_t len, const string &str);(3)删除某个子串的函数:string &erase (size_t pos = 0, size_t len = npos);(4)在字符串前面补充某字符的函数:string &insert (size_t pos, size_t n, char c);(5)清除字符串的函数:void clear();6、string类的截取操作string类的截取操作有以下几种:(1)从某个位置截取字符串的函数:string substr (size_t pos = 0, size_t n = npos);(2)将字符串按照一定的字符分割成多个小字符串的函数:vector<string> split(char c);(3)删除收尾处的某字符的函数:string &trim(char c);。
编写strcpy函数和类String的构造函数、析构函数、赋值函数和重载运算符函数已知strcpy函数的原型是char *strcpy(char *strDest, const char *strSrc);其中strDest是目的字符串,strSrc是源字符串。
(1)不调用C++/C的字符串库函数,请编写函数strcpychar *strcpy(char *strDest, const char *strSrc); //将源字符串加const,表明其为输入参数{assert((strDest!=NULL) && (strSrc !=NULL)); // 2分 //对源地址和目的地址加非0断言char *address = strDest; // 2分//为了实现链式操作,将目的地址返回while( (*strDest++ = * strSrc++) != …\0‟ ) // 2分NULL ;return address ; // 2分}(2)strcpy能把strSrc的内容复制到strDest,为什么还要char * 类型的返回值?答:为了实现链式表达式。
// 2分例如int length = strlen( strcpy( strDest, “hello world”) );二、网上广泛流传的,也是摘自林锐的http://www.blog.sh/user3/skyflowing/archives/2006/60452.html题目:已知strcpy函数的原型是:char * strcpy(char * strDest,const char * strSrc);1.不调用库函数,实现strcpy函数。
2.解释为什么要返回char *。
解说:1.strcpy的实现代码char * strcpy(char * strDest,const char * strSrc){if ((strDest==NULL)||(strsrc="/=NULL"))//[1](我感觉应为&&)throw "Invalid argument(s)";//[2]char * strDestCopy=strDest;//[3]while ((*strDest++=*strSrc++)!='\0');//[4]return strDestCopy;}错误的做法:[1](A)不检查指针的有效性,说明答题者不注重代码的健壮性。
(B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),说明答题者对C语言中类型的隐式转换没有深刻认识。
在本例中char *转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。
所以C++专门增加了bool、true、false三个关键字以提供更安全的条件表达式。
(C)检查指针的有效性时使用((strDest==0)||(strsrc="/=0")),说明答题者不知道使用常量的好处。
直接使用字面常量(如本例中的0)会减少程序的可维护性。
0虽然简单,但程序中可能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程序内含逻辑错误,很难排除。
而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。
[2](A)return new string("Invalid argument(s)");,说明答题者根本不知道返回值的用途,并且他对内存泄漏也没有警惕心。
从函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。
(B)return 0;,说明答题者没有掌握异常机制。
调用者有可能忘记检查返回值,调用者还可能无法检查返回值(见后面的链式表达式)。
妄想让返回值肩负返回正确值和异常值的双重功能,其结果往往是两种功能都失效。
应该以抛出异常来代替返回值,这样可以减轻调用者的负担、使错误不会被忽略、增强程序的可维护性。
[3](A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。
[4](A)循环写成while (*strDest++=*strSrc++);,同[1](B)。
(B)循环写成while (*strSrc!='\0') *strDest++=*strSrc++;,说明答题者对边界条件的检查不力。
循环体结束后,strDest字符串的末尾没有正确地加上'\0'。
2.返回strDest的原始值使函数能够支持链式表达式,增加了函数的“附加值”。
同样功能的函数,如果能合理地提高的可用性,自然就更加理想。
链式表达式的形式如:int iLength=strlen(strcpy(strA,strB));又如:char * strA=strcpy(new char[10],strB);返回strSrc的原始值是错误的。
其一,源字符串肯定是已知的,返回它没有意义。
其二,不能支持形如第二例的表达式。
其三,为了保护源字符串,形参用const限定strSrc所指的内容,把const char *作为char *返回,类型不符,编译报错。
类似的我们可以写出一个10分的strlen函数int strlen( const char *str ) //输入参数const{assert( strt != NULL ); //断言字符串地址非0int len;while( (*str++) != '\0' ){len++;}return len;}include <cstring>#include <iostream>using namespace std;//已知类String的原型为:class String{public:String(const char *str = NULL); // 普通构造函数String(const String &o ther); // 拷贝构造函数~ String(void); // 析构函数String& operato r =(const String &other); // 赋值函数String& operato r +(const String &other); //重载运算符+String& operato r -(const String &other); //重载运算符-bool operator==(const String &o ther); //重载"==",判断两个字符串相等bool operator<(const String &o ther);bool operator>(const String &o ther);friend ostream& operato r << (ostream &, const String &); //重载<<,这里必须使用friend,因为涉及到两个类之间私有成员的访问private:char *m_data; // 用于保存字符串};//请编写String的上述4个函数。
//普通构造函数String::String(const char *str){if(NULL==str){m_data = new char[1]; // 得分点:对空字符串自动申请存放结束标志'\0'的//加分点:对m_data加NULL 判断if(m_data!=NULL)*m_data = '\0';}else{int length = strlen(str);m_data = new char[length+1]; // 若能加NULL 判断则更好if(m_data!=NULL)strcpy(m_data, str);}}// String的析构函数String::~String(void){delete [] m_data; // 或delete m_data;}//拷贝构造函数String::String(const String &o ther) // 得分点:输入参数为const型{int length = strlen(other.m_data);m_data = new char[length+1]; //加分点:对m_data加NULL 判断if(m_data!=NULL)strcpy(m_data, o ther.m_data);}//赋值函数String& String::operato r=(const String &other) // 得分点:输入参数为const型{if(this == &other) //得分点:检查自赋值return *this;delete [] m_data; //得分点:释放原有的内存资源int length = strlen( other.m_data );m_data = new char[length+1]; //加分点:对m_data加NULL 判断if(m_data!=NULL)strcpy( m_data, o ther.m_data );return *this; //得分点:返回本对象的引用}String& String::operato r+(const String &other) //重载运算符+ {char temp[200];strcpy(temp,m_data);delete [] m_data;int length=strlen(this->m_data)+strlen(other.m_data);m_data=new char[length+1];if(m_data!=NULL)strcpy(m_data,temp);strcat(m_data,o ther.m_data);return *this;}String& String::operato r-(const String &other){char *temp,*p;if( (temp=strstr(m_data,other.m_data)) ==NULL){cout<<"没有符合的子串,不能使用'-'操作"<<endl;return *this;}else{p=temp;temp=temp+strlen(other.m_data);*p='\0';strcat(m_data,temp);}return *this;}//重载运算符"<<"ostream& operator<<(ostream &output, const String &other){output<<other.m_data;return output;}bool String::operator<(const String &o ther){if(strcmp(m_data,other.m_data)<0)return true;return false;}bool String::operator>(const String &o ther) {if(strcmp(m_data,other.m_data)>0)return true;return false;}bool String::operator==(const String &other) {if(strcmp(m_data,other.m_data)==0)return true;return false;}void main(){String s1("Hello,");String s2("World!");String s3(s2);//调用拷贝构造函数String s4(s2);String s5("Hello,World");String s6("Hello,World!");String s7("Hello,World!");String s8("o,W");String s9;//String s3;//调用构造函数中的默认构造.//s3=s2;// 调用重载后的赋值函数cout<<s1<<endl;cout<<s2<<endl;cout<<s3<<endl;s3=s1+s2;cout<<s1<<endl;cout<<s2<<endl;cout<<s3<<endl;if(s4==s2)cout<<"两个字符串相等"<<endl;elsecout<<"两个字符串不相等"<<endl;if(s5<s6)cout<<"s5小于s6"<<endl;else if(s5>s6)cout<<"s5大于s6"<<endl;elsecout<<"s5等于s6"<<endl;s9=s7-s8;cout<<s9<<endl;system("pause");}原文:/rgaofei/blog/item/f538fc081b332333b0351dd0.html。