【C++学习笔记】通过自定义string类,学习类相关知识

目标

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());
    
    
    
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值