目标
1 类相关的概念的学习
学习链接runoob:https://www.runoob.com/cplusplus/cpp-classes-objects.html
2 练习
实现mystring类,包含string类的方法如下;
- 成员函数
- 构造函数
- 析构函数
- operator=
元素访问
- at
- operator[]
容量
- size
- length
- empty
参考链接:
c++类方法参考(中文):https://zh.cppreference.com/w/cpp/string/basic_string
c++类方法参考(英文):http://www.cplusplus.com/reference/string/string/
const关键字小结:https://www.runoob.com/w3cnote/cpp-const-keyword.html
C++编译出错:discards qualifiers [-fpermissive]:https://blog.youkuaiyun.com/nanjiye/article/details/52138234
delete []和delete区别:https://www.cnblogs.com/wangjian8888/p/7905176.html
小结
1 类存在隐性的构造函数和operator=函数,默认的=会先以右操作数初始化对象,在进行赋值,感兴趣的可以跟踪代码看;
2 C++注重规范性,强调期望和实际的一致,符合const的时候,以const标识;
3 类中存在指针,需要实现拷贝构造函数;
windows, 使用g++编译, 运行结果如下:
D:\Cpp_prj\mystring_gcc>g++ test.cpp mystring.cpp -o main
D:\Cpp_prj\mystring_gcc>main
~~~1 Test:MyString(char*)
str1: should be ABCD,actual:ABCD
~~~2 Test:MyString(int n, char)
str2:should be AAA,actual:AAA
~~~3 Test:MyString(),operator =
str4:should be ABCD,actual:ABCD
~~~4 Test:MyString(const MyString&)
str3should be ABCD,actual:ABCD
~~~5 operator =
str4 should be ABCD,actual:ABCD
~~~5.1 Test:at
Test:at should be D, actual: D
~~~5.2 Test:at out of range
Test:at should be out of range, actual: Position out of range
~~~6 operator[]
Test:at should be C, actual: C
~~~7 capacity relative:length: size
str1 size should be 4, actual:4
str2 size should be 3, actual:3
~~~7 capacity relative: empty
str4 should not be empty, actual:not empty
代码如下:
test.cpp – 比较暴力,直接打印看的,初学c++,还没有看断言怎么写。 – 5月26日,添加断言,详见test_assert.cpp
#include <iostream>
#include "mystring.h"
using namespace std;
int main() {
cout << "~~~1 Test:MyString(char*)"<<endl;
MyString str1("ABCD");
cout << "str1: should be ABCD,actual:" << str1 << endl;
cout <<endl<< "~~~2 Test:MyString(int n, char)"<<endl;
MyString str2(3,'A');
cout << "str2:should be AAA,actual:" << str2 << endl;
cout <<endl<< "~~~3 Test:MyString(),operator ="<<endl;
MyString str4;
str4 = str1;
cout << "str4:should be ABCD,actual:" << str4 << endl;
cout <<endl<< "~~~4 Test:MyString(const MyString&)"<<endl;
MyString str3(str1);
cout << "str3should be ABCD,actual:" << str3 << endl;
cout <<endl<< "~~~5 operator ="<<endl;
str4 = str1;
cout << "str4 should be ABCD,actual:" << str4 << endl;
cout <<endl<< "~~~5.1 Test:at"<<endl;
cout << "Test:at should be D, actual: "<< str4.at(3) << endl;
cout <<endl<< "~~~5.2 Test:at out of range"<<endl;
cout << "Test:at should be out of range, actual: "<< str4.at(4) << endl;
cout <<endl<< "~~~6 operator[]"<<endl;
cout << "Test:at should be C, actual: "<< str4[2] << endl;
cout <<endl<< "~~~7 capacity relative:length: size"<<endl;
cout << "str1 size should be 4, actual:" << str1.size() << endl;
cout << "str2 size should be 3, actual:" << str2.length() << endl;
cout <<endl<< "~~~7 capacity relative: empty"<<endl;
cout << "str4 should not be empty, actual:" << (str4.empty()?"empty":"not empty") << endl;
};
mystring.h
#ifndef __MYSTRING__
#define __MYSTRING__
#include <iostream>
using namespace std;
class MyString
{
public:
MyString();
MyString(const char*);
MyString(int n, char);
MyString(const MyString&);
~MyString();
public:
MyString& operator=(const MyString&);
// MyString operator=(const char*);
char operator[](int);
char at(int position);
friend istream& operator>>(istream&, MyString&);
friend ostream& operator<<(ostream&, const MyString&);
public:
int length() const;
int size() const;
bool empty() const;
private:
char* str;
};
#endif
mystring.cpp
#include <iostream>
#include <cstring>
#include "mystring.h"
// #define TRACE_FUNCTION (cout <<"call:" << __FILE__<<"("<< __LINE__<<"):"<<__FUNCTION__ <<endl)
#define TRACE_FUNCTION
using namespace std;
//无参构造函数
MyString::MyString()
{
TRACE_FUNCTION;
str = NULL;
}
//带一个参数的构造函数
MyString::MyString(const char *t_str)
{
TRACE_FUNCTION;
str = new char[strlen(t_str)];
strcpy(str,t_str);
}
//带两个参数的构造函数
MyString::MyString(int n, char t_char)
{
TRACE_FUNCTION;
str = new char[n];
for (int i = 0; i < n; i++)
{
*(str+i) = t_char;
}
}
// 拷贝构造函数,因为MyString类中有指针,故拷贝构造函数要重写
MyString::MyString(const MyString& t_str)
{
TRACE_FUNCTION;
str = new char[strlen(t_str.str)];
strcpy(str, t_str.str);
}
MyString& MyString::operator=(const MyString& t_str)
{
TRACE_FUNCTION;
if(this != &t_str)
{
delete []str;
str = new char[strlen(t_str.str)];
strcpy(str, t_str.str);
}
return *this;
}
MyString MyString::operator+(const MyString& t_str)
{
TRACE_FUNCTION;
char *tmp = new char[size() + t_str.size()];
strcpy(tmp,str);
strcat(tmp,t_str.str);
MyString tmp1(tmp);
return tmp1;
}
// MyString MyString::operator=(const char* chr)
// {
// TRACE_FUNCTION;
// delete []str;
// str = new char[strlen(chr)];
// cout << "call: MyString MyString::operator="<<endl;
// strcpy(str, chr);
// return *this;
// }
//析构函数
MyString::~MyString()
{
TRACE_FUNCTION;
delete []str;
}
int MyString::length() const
{
TRACE_FUNCTION;
return strlen(str);
}
int MyString::size() const
{
TRACE_FUNCTION;
return length();
}
bool MyString::operator==(const MyString& t_str) const
{
TRACE_FUNCTION;
// return (*str == *(t_str.str) ? true : false);//这样会有问题,只比较了第一地址的字符;
return (strcmp(str,t_str.str) == 0 ? true : false);
}
bool MyString::empty() const
{
TRACE_FUNCTION;
return this->size() == 0 ? true : false;
}
//重载[]操作符
char MyString::operator[](int position)
{
TRACE_FUNCTION;
return *(str + position);
}
char MyString::at(int position)
{
TRACE_FUNCTION;
try{
if(position >= this->size())
{
throw position;
}
return *(str + position);
}
catch(int)
{
cout << "Position out of range" << endl;
return '\0';
}
}
//重载>>操作符
istream& operator>>(istream &is, MyString &t_str)
{
TRACE_FUNCTION;
is >> t_str.str;
return is;
}
//重载<<操作符
ostream& operator<<(ostream &os, const MyString &t_str)
{
TRACE_FUNCTION;
os << t_str.str;
return os;
}
test_assert.cpp – 补充断言的方式,验证函数的正确性
#include <iostream>
#include "mystring.h"
// #define NDEBUG
#include <assert.h>
using namespace std;
int main() {
cout << "~~~1 Test:MyString(char*)"<<endl;
MyString str1("ABCD");
assert(str1 == "ABCD");
cout <<endl<< "~~~2 Test:MyString(int n, char)"<<endl;
MyString str2(3,'A');
assert(str2 == "AAA");
cout <<endl<< "~~~3 Test:MyString(),operator ="<<endl;
MyString str4;
str4 = str1;
assert(str4 == "ABCD");
cout <<endl<< "~~~4 Test:MyString(const MyString&)"<<endl;
MyString str3(str1);
assert(str3 == "ABCD");
cout <<endl<< "~~~5 operator ="<<endl;
str4 = str1;
assert(str4 == str1);
cout <<endl<< "~~~5.1 Test:at"<<endl;
assert('D' == str4.at(3));
cout <<endl<< "~~~5.2 Test:at out of range"<<endl;
cout << "Test:at should be out of range, actual: "<< str4.at(4) << endl;
cout <<endl<< "~~~5.3 operator +"<<endl;
MyString str5;
str5 = str1 + "E";
assert(str5 == "ABCDE");
cout <<endl<< "~~~6 operator[]"<<endl;
assert('C' == str4[2]);
cout <<endl<< "~~~7.1 capacity relative:length: size"<<endl;
assert( 4 == str1.size());
assert( 3 == str2.length());
cout <<endl<< "~~~7.2 capacity relative: empty"<<endl;
assert(false == str4.empty());
cout <<endl<< "~~~7.1 capacity relative:length: size"<<endl;
assert( 4 == str1.size());
};