?涉及到的内容包括:构造、拷贝构造、赋值、析构、输入输出的重载函数、友元函数 、strlen、 strcpy、 explict关键字。
字符串的最后以'\0'结尾,即便是空字符串也需要动态申请一个char的动态空间,存放'\0';
strlen统计字符串长度,不计算'\0';
strcpy 复制内容,会复制最后一位的'\0';
拷贝构造、赋值函数的传入形参是const类型;
赋值函数为了能连续赋值,返回值类型是引用型;
输入输出的操作符重载同样为了能连续赋值,返回值是引用型;
cin、cout本身就是istream、ostream类,直接cin>>mystring,需要mystring.operator >>(cin),另一种方法就是声明友元函数,使得iostream类能访问Mytring类的成员。注意虽然友元函数不属于成员函数。
explict表示不能隐式调用函数,传入的参数必须与类内定义的样子一模一样,不能作转换。
Mystring s("asdf");//是将asdf转换成了char* ptr,再调用构造函数的,如果explict Mystring(char*ptr=nullptr)就会报错了
//自定义string类的实现
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<bits/stdc++.h>
using namespace std;
class Mystring{
public:
Mystring(char *ptr= nullptr)
{
if(ptr== nullptr){
mdata=new char[1];
*mdata='\0';
mlength=0;
}
else{
mlength=strlen(ptr); //strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符’\0’为止,然后返回计数器值。
mdata=new char[mlength+1];
strcpy(mdata,ptr);//strcpy是一种C语言的标准库函数,strcpy把从src地址开始且含有’\0’结束符的字符串复制到以dest开始的地址空间,返回值的类型为char*。
}
cout<<"constucted!"<<endl;
}
Mystring(const Mystring& str)
{
mlength= strlen(str.mdata);
mdata=new char[mlength+1];
strcpy(mdata,str.mdata);
cout<<"copy construct"<<endl;
}
Mystring& operator=(const Mystring& str)
{
if(this!=&str){
Mystring tmp=Mystring(str);
swap(this->mdata,tmp.mdata);
}
cout<<"assign"<<endl;
return *this;
}
//重载输入、输出的运算符
istream& operator>>(istream &is){//类内成员函数比友元函数少一个参数
char temp[1000];
is>>temp;
mlength= strlen(temp);
mdata=new char[mlength+1];
strcpy(mdata,temp);
return is;
}
//cin>>mystring;//为什么不行呢? 而调用成员函数的方式就可以,为什么这里编译器不能自动将cin>>mytring进行转换成mystring.operator>>(cin);
//解决办法:将输入输出流定义为友元 因为直接cin是外部的另一个类,无法调用Mystring类的成员函数函数,声明为友元的话,就可以进行调用类里的函数
//类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
friend istream & operator>>(istream& is,Mystring& str){
char temp[1000];
is>>temp;
str.mlength= strlen(temp);
str.mdata=new char[str.mlength+1];
strcpy(str.mdata,temp);
return is;
}
ostream& operator<<(ostream&os){
cout<<mdata<<endl;
return os;
}
virtual size_t msize(){
return 0;
}
~Mystring()
{
delete[] mdata;//注意是delete []
cout<<"destroyed!"<<endl;
}
private:
char * mdata;
size_t mlength;
};
class se:Mystring{
public:
size_t msize(){//派生类不能直接访问基类的私有成员,若要访问必须使用基类的接口,即通过其成员函数。
//return mlenth;//访问基类的私有成员是有问题的
return 0;
}
};
int main() {
Mystring mystring("abcd");//会调用隐式构造函数,加上explicit就会报错了
cin>>mystring;//调用友元函数,参数是两个,访问mystring类的内部成员变量和成员函数 cin和一般的+、-重载不同,本身cin也是一个类。
//mystring.operator>>(cin);//调用类内的成员函数
mystring.operator<<(cout);
Mystring mystring1(mystring);
Mystring mystring2;
mystring2=mystring;
//为什么不能直接Mystring mystring2=mystring 会调用隐式复制构造函数即Mystring mystring2(mystring);
return 0;
}
|