用重载运算符封装string类:=表示赋值,+表示产生一个新的字符串(用strcat来实现,不等同于实现strcat),==表示判断是否相等。//这里是我没理解题意,尤其是+重载
c=a+b; a=b; c明显是个新的对象,所以返回值用Mystring
为了便于理解,我又写了个重载+=
#include
#include
#include
using namespace std;
class String{
public:
String(const char *str)
{
int len = strlen(str)+1;
ptr = new char [len];
assert(NULL != ptr);
strcpy(ptr,str);
}
~String()
{
delete [] ptr;
}
public:
String operator +(const String &obj)
{
int len = strlen(this->ptr) + strlen(obj.ptr) + 1;//计算长度
char *p = new char [len];
assert(NULL != p);
strcpy(p,this->ptr);
strcat(p,obj.ptr);
String tmp(p);//构造对象
delete [] p;
return tmp;
}
String & operator =(const String &obj)
{
int len = strlen(obj.ptr)+1;
delete [] ptr;
ptr = new char[len];
assert(NULL != ptr);
strcpy(this->ptr, obj.ptr);
return *this;
}
String & operator +=(const String &obj) //重载+=
{
int len = strlen(obj.ptr)+strlen(this->ptr)+1;
char *p = new char[len];
strcpy(p,this->ptr);
strcat(p,obj.ptr);
delete [] ptr;
ptr = new char[len];
assert(NULL != ptr);
strcpy(this->ptr, p);
delete [] p;
return *this;
}
int operator == (const String &obj)
{
return ((strcmp(this->ptr,obj.ptr) == 0) ? 1 : 0);
}
int operator != (const String &obj)
{
return ((strcmp(this->ptr,obj.ptr) == 0) ? 0 : 1);
}
friend ostream & operator << (ostream &, const String &);
private:
char *ptr;
};
ostream & operator << (ostream &os, const String &obj)
{
os << obj.ptr;
return os;
}
int main()
{
String a = "hello";
String b = "world";
String c = a+b;
cout << c << endl;
a = b;
cout << a << endl;
cout << b << endl;
a = c;
cout << (a == b) << endl;
return 0;
}
C | 不能有函数,但可以有函数指针 |
C++ | 可以有函数,默认权限public |
C++结构体 | 默认public |
C++类 | 默认private |
面向过程/对象 | C主要面向过程,C++主要面向对象(侧重于类的设计而非逻辑) |
适用方向不同 | C要求效率高代码体积小(如Linux系统就是C编写的),C++适用于更上层 |
C++是C的扩充 |
操作方式 | 指针是存变量地址(间接),引用是取别名(直接) |
内存 | 指针占内存,引用不占内存 |
指向 | 指针可以为空且可更改,引用必须初始化且不可更改 |
指针有多级指针 |
修饰局部变量 | 延长生命周期,程序结束释放(ps:循环中还能防止重复定义) |
修饰全局变量 | 限制本文件使用(全局变量定义在源.c文件中) |
修饰函数 | 限制本文件使用 |
值传递 | int |
地址传递 | int * |
引用传递 | int & |
C | 宏定义(编译阶段) |
C++ | inline |
宏,用于检查不应该发生的情况,比如assert(ptr!=NULL);好用 C中也能用 |
const更安全 | const有数据类型,编译器可以进行安全检查,后者只是单纯的字符替换 |
const可以调试 | 宏定义不能 |
本质不同 | malloc是C/C++库函数,new是C++运算符 |
C++对象需要 | 方便编译阶段执行构造函数和析构函数时,创建/释放空间。(而库函数不在编译器的控制权限之内) new:动态内存分配和初始化 delete:清理和释放内存 |
溢出 | 内存不够导致申请内存失败 |
泄露 | 无法成功释放内存,导致内存堆积 |
malloc(0) | 返回一个空指针。检查返回值是否为NULL来判断是否能够正常动态分配内存 |
解决内存溢出 | 异常处理函数 if(ptr==NULL) return -1;或者 assert(ptr!=NULL); |
模板是泛型编程的基础
泛型编程:编写与类无关的代码 //主函数使用举例:add
总结:
头部声明:template
外部定义:template
作用域访问符:Demo::
主函数:Demo obj;
#include
using namespace std;
//函数模板声明
template //T:int\double\char\Demo... 这里class和类无关
T add(T &a, T &b);
class Demo{
public:
Demo(int val) : val(val)
{
cout << __func__ << ":" << __LINE__ << endl;
}
public:
void setval(int val)
{
this->val = val;
}
int getval() const
{
return this->val;
}
private:
int val;
};
template
T add(T &a,T &b)
{
T c = a+b;
return c;
}
int main()
{
int m = 10;
int n = 20;
double d = 1.2;
double e = 2.3;
Demo a(333);
Demo b(333);
int ret = add(m,n);//T:int
cout << ret << endl;
double f = add(d,e);//T:double
cout << f << endl;
Demo c = add(a,b);//T:Demo
cout << c << endl;
return 0;
}
//主函数使用举例:Demo
类模板的构造函数不能给定默认值(T都不确定)
总结:
比上个函数模板,区别在于头部声明紧跟类
头部声明:template
外部定义:template
作用域访问符:Demo
主函数:Demo
#include
using namespace std;
template
class Demo{
public:
Demo(T val):val(val){
cout << __func__ << ":" << __LINE__ << endl;
}
void setval(T val);
T getval() const;
private:
int val;
};
template
void Demo::setval(T val)
{
this->val = val;
}
template //外部定义必须加模板声明
int Demo::geival()
{
return this->val;
}
int main()
{
Demo obj(100);
obj.setval(200);
cout<
template
class Demo{
};
//注意index还是用int,不用T
总结:
比上个类模板,头部声明多了确定的参数类型,需要主函数创建对象时初始化
头部声明:template
外部定义:template
作用域访问符:Array
主函数:Array
#include
#include
using namespace std;
template //len表示数组长度
class Array{
public:
Array(){
ptr = new T[len];
assert(ptr!=NULL);
}
~Array(){
delete [] ptr;
}
public:
void setval(int index,T val); //index就可以不用T?
T getval(int index) const;
private:
T *ptr;
};
template
T Array::getval(int index) const
{
return ptr[index];
}
int main()
{
Array a; //记得主函数用一个整数表示len
int i;
for(i=0;i<10;i++) //注意这里和数组长度对应
{
a.setval(i,i+1); //还是不习惯对象访问
}
for(i=0;i<10;i++)
{
cout<
给类模板的形参指定默认值
template
总结:
比上个非类型模板参数,区别在于头部声明(加具体值)和主函数使用(可覆盖)
头部声明:template
外部定义:template
作用域访问符:Array
主函数:Array
#include
#include
using namespace std;
template
class Array{
public:
Array(){
ptr = new T[len];
assert(ptr!=NULL);
}
~Array()
{
delete [] ptr;
}
public:
void setval(T val,int pos);
T getval(int pos) const;
private:
T val;
};
template
//类外部成员函数定义的时候就不加具体默认值,template
void Array::setval(T val,int pos) //Array
{
ptr[index] = val;
}
template
T Array::getval(int pos) const
{
return ptr[index];
}
int main()
{
Array obj;
Array<> obj2; //也可以就用默认参数,不传参
return 0;
}
#include
using namespace std;
template
class Demo
{
public:
Demo(T val) : val(val)
{
cout << __func__ << ":" << __LINE__ << endl;
}
Demo(const Demo &obj) //拷贝构造函数
{
cout << __func__ << ":" << __LINE__ << endl;
this->val = obj.val;
}
~Demo()
{
cout << __func__ << ":" << __LINE__ << endl;
}
void setval(T val)
{
this->val = val;
}
T getval() const;
template
friend ostream &operator <<(ostream &,const Demo &);//友元模板函数
private:
T val;
};
//类外部定义成员方法
template
T Demo::getval() const
{
return this->val;
}
template
ostream &operator <<(ostream &os,const Demo & obj)
{
os << obj.val;
return os;
}
int main()
{
Demo obj(666);
Demo obj1 = obj;
cout << obj << endl;
cout << obj1 << endl;
Demo obj2(1.2);
cout << obj2 << endl;
return 0;
}
头部声明:template
内部friend函数声明:template
外部定义:template
外部friend函数定义:template
作用域访问符:Demo
主函数:Demo