C++面向对象是区别于C的典型特征,C++中类有两种不同的类型。
- 数据成员不含指针的;典型代表有Complex类。
- 数据成员含指针的;典型为字符串String类。
C++11中提出了新概念move semantics(可译为移动语义),可以简单理解为移动语义为**“浅拷贝”**,具体可查资料了解。
下面贴出String类的具体代码:
#ifndef __STRING_H_
#define __STRING_H_
#include <cstring>
#include <iostream>
//典型String类的编写
class String {
public:
String(const char* cstr = 0, int clen = 0);
String(const String& str);
String(String&& str);
String& operator=(const String& str);
String& operator=(String&& str);
~String();
int size() const{
return len;
}
char* get_c_str() const {
return pstr;
}
private:
char* pstr;
int len;
};
inline
String::String(const char* cstr, int clen) { // 声明的时候有默认值,定义的时候不需要默认值,会出现重定义错误
std::cout << "调用了ctor" << "\n";
if (cstr) {
pstr = new char[strlen(cstr) + 1];
len = strlen(cstr);
strcpy(pstr, cstr);
}
else {
pstr = new char[1];
len = 0;
*pstr = '\0';
}
}
inline
String::String(const String& str) {
std::cout << "调用了copy ctor" << "\n";
pstr = new char[str.len + 1];
len = str.len;
strcpy(pstr, str.pstr);
}
inline
String& String::operator=(const String& str) {
std::cout << "调用了copy assignment" << "\n";
if (this == &str) {
return *this;
}
delete[] pstr;
pstr = new char[str.len + 1]; /* 类的拷贝复制和拷贝构造乃至成员函数都能访问同类形参中的私有变量 */
len = str.len;
strcpy(pstr, str.pstr);
return *this;
}
inline
String::String(String&& str) {
std::cout << "调用了move ctor" << std::endl;
if (str.pstr != NULL) {
pstr = str.pstr;
str.pstr = nullptr;
len = str.len;
}
}
inline
String& String::operator=(String&& str) {
std::cout << "调用了move assignment" << std::endl;
if (this != &str) {
delete[] pstr;
pstr = str.pstr;
str.pstr = nullptr;
len = str.len;
}
return *this;
}
inline
String::~String() {
std::cout << "调用了dtor" << "\n";
delete[] pstr;
}
/* 将operator<<重载为全局函数好一点(相比于重载为成员函数)
1. 重载为成员函数
ostream& operator<<(ostream& os) {
os << pstr;
return os;
}
调用的时候只能这样调用:s << cout(即 s.operator<<(cout)), 和我们的常用手法相悖
2. 重载为全局函数
*/
std::ostream& operator<<(std::ostream& os, const String& s) {
os << s.get_c_str();
return os;
}
// 还可以重载operator<,用来比较两个String的大小
bool operator<(const String& s1, const String& s2) {
return strcmp(s1.get_c_str(), s2.get_c_str()) < 0;
}
#endif //__STRING_H_
下面贴出测试代码:
#include <iostream>
#include "string.h"
using namespace std;
int main(int argc, char** argv) {
String s1("Ray");
String s2("Shan");
String s3(s2);
String s4 = s3;
//test move ctor
String s5(std::move(s1));
//test move assignment
s4 = move(s2);
s3 = s4;
if (s5 < s4) {
cout << s5 << " < " << s4 << endl;
}
else {
cout << s5 << " >= " << s4 << endl;
}
cout << s5 << "\n" << s4 << "\n";
cout << s3 << "的长度为" << s3.size() << "\n";
return 0;
}
结果:
右值引用的拷贝构造和拷贝赋值函数中的参数都不能加const。