String类的实现与思考

对于字符串我们有时候很难向整型或其他变量那样进行比较和直接复制或定义,这都是C语言中遇到的问题,在C++ 中提供了一种类专门解决这种对于字符串的操作,叫做string类,我其实也想实现一下并且暂时浅浅的了解一下,以下是我简单的实现string类,我的string叫 String类注意大小写哦!!!!!!!!!

/*/**********************************************************************
* *   Copyright (c)2015,WK Studio
* *   Filename:  String.h
* *   Compiler: GCC  vs2013
* *   Author:WK
* *   Time: 2015 14 6
* **********************************************************************/
#include<iostream>
#include<string.h>
using namespace std;

class String
{
public:
	String(char * d) :data(d)
	{}
	//构造函数
	String(const char *str = NULL);
	~String();
	String(const String &s);
	String& operator=(const String &s);
	friend String operator + (const String& str1, const String& str2);

	String& operator+=(const String &str2);
	friend String& operator+=(String &str1, String &str2);

	friend bool operator!=(String &str1, String &str2);
	friend bool operator==(String &str1, String &str2);
	friend bool operator>(String &str1, String &str2);
	friend bool operator<(String &str1, String &str2);
	/*
	对“ << ”和“ >> ”重载的函数形式如下:
	istream & operator >> (istream &, 自定义类 &);
	ostream & operator << (ostream &, 自定义类 &);
	即重载运算符“ >> ”的函数的第一个参数和函数的类型都必须是istream&类型,第二个参数是要进行输入操作的类。重载“ << ”的函数的第一个参数和函数的类型都必须是ostream&类型,第二个参数是要进行输出操作的类。因此,只能将重载“ >> ”和“ << ”的函数作为友元函数或普通的函数,而不能将它们定义为成员函数。
	*/
	friend istream& operator>> (istream &is, String &str);//返回引用可以实现连续输入,并且返回值不存在与栈中所以可以返回引用
	friend ostream& operator<< (ostream &out, String &str);

private:
	char *data;
};
/*/**********************************************************************
* *   Copyright (c)2015,WK Studio
* *   Filename:  main.cpp
* *   Compiler: GCC  vs2013
* *   Author:WK
* *   Time: 2015 14 6
* **********************************************************************/

void main()
{

	String s1 = "Str";//调用构造
	String s2("ing");//调用构造

	String s3 = s1;//调用拷贝

	String s4("String");//调用构造
	s4 = s2;//调用赋值
	String s5;//调用构造
    s5 = s2;//调用赋值

	String s6("String");//调用构造
	s6 = s1 + s2;//调用+运算符重载函数返回临时无名对象通过临时无名对象调用赋值函数对s6进行赋值,之后临时无名对象被释放
	String s7;
	s7 = s1 + s2;//同上
	String  s8 = s1 + "123";//调用构造函数用"123"生成一个临时对象来和s1进行相加调用+运算符重载

   String s9 = s1 + s2;//+运算符重载返回的临时无名对象直接用来拷贝构造s8对象

   String s10;
   s10+= s1;//如果+=运算符重载的友员和成员函数都存在调用的是友元函数
   //s9.operator+=(s1);//调用成员函数
   //operator+=(s9,s1);//可以直接调用友员函数,因为友员函数属于类无需对象来驱动
   //String s10 += s2;
   //上面这种不可以是因为在+=之前是s10对象还没有构造呢
   //类似于int a = 10;  int b+= a;  int c+=1;
   String ss("1");
   String ss1("1");
   cout << (s1 != s2) << "\n";
   cout << (ss != ss1) << "\n";
   cout << (ss == ss1) << "\n";
   cout << (s1 == s2) << "\n";

   cout << (s1 > s2) << "\n";
   cout << (s1 < s2) << "\n";
   String s11;
   cin >> s11;

   cout << s11;
   getchar();

}
/*/**********************************************************************
* *   Copyright (c)2015,WK Studio
* *   Filename: String.cpp
* *   Compiler: GCC  vs2013
* *   Author:WK
* *   Time: 2015 14 6
* **********************************************************************/
#include"String.h"
//构造函数
String::String(const char *str)
{
	cout << "Create String!" << this << "\n";
	if (str == NULL)
	{
		data = new char[1];//至少有一个'\0'
		data[0] = '\0';
	}
	else
	{
		data = new char[strlen(str) + 1]; //(char *)malloc(strlen(str)+1);
		strcpy(data, str);
	}
}
/*//构造函数1
String(const char *str = NULL)
{
if(str == NULL)
{
str=NULL;    //不能满足当字符串为NULL时候
}
else
{
data = new char[strlen(str)+1];//(char *)malloc(strlen(str)+1);
strcpy(data,str);
}
}
//构造函数2
String(const char *str = "")//不能满足当字符串为NULL时候
{
data = new char[strlen(str)+1];//(char *)malloc(strlen(str)+1);
strcpy(data,str);
}
*/
//拷贝构造
String::String(const String &s)
{
	cout << "Copy String!" << this << "\n";
	data = new char[strlen(s.data) + 1];
	strcpy(data, s.data);
}

//= 运算符重载
String& String:: operator=(const String &s)//返回引用可以实现连等
{
	cout << "Assignment String!" << this << "\n";
	if (this != &s)   //(1) 检查自赋值
	{
		free(this->data);  // (2) 释放原有的内存资源
		this->data = NULL;
		this->data = new char[strlen(s.data) + 1];// (3)分配新的内存资源,并复制内容
		strcpy(this->data, s.data);
	}
	return *this;    // (4)返回本对象的引用
}
/*
String& operator=(const String &s)
{
if(this==&s)//(1) 检查自赋值
{
return *this;
}
free(this->data); // (2) 释放原有的内存资源
data=NULL;

data=new char[strlen(s)+1];//(3)分配新的内存资源,并复制内容
strcpy(data,s.data);

return *this; // (4)返回本对象的引用

}
*/
//运算符+重载为友员函数
String operator + (const String& str1, const String& str2)//不可以返回引用,因为这里在函数栈中建立了一个临时的对象,具体讨论青参照我的这篇文章
{
	String str;//临时对象调用构造函数
	delete[] str.data;
	str.data = NULL;
	str.data = new char[strlen(str1.data)+strlen(str2.data) + 1];
	strcpy(str.data, str1.data);
	strcat(str.data, str2.data);
	cout << "+ operator String!"<< "\n";
	return str;//这里会调用拷贝构造函数用str对象拷贝构造临时无名对象,之后在栈中将临时对象释放
}
//+=运算符重载为成员函数
String& String:: operator+=(const String &str2)
{
	if (this != &str2)
	{
		*this = *this + str2;
	}
	cout << "+=运算符成员函数重载!\n";
	return *this;
}
//+=运算符重载为友元函数
String& operator+=(String &str1, String &str2)//可以返回引用,因为这里的str1超过这个函数栈还存在
{
	if (&str1 != &str2)//当将!=运算符重载之后可以使用(str1!=str2)进行判断了
	{
		str1 = str1 + str2;
	}
	cout<< "+=运算符友员函数重载!\n";
	return str1;
}
//!=重载函数
bool operator!=(String &str1, String &str2)
{
	if (!strcmp(str1.data, str2.data))
	{
		cout << "These String is equal!\n";
		return false;
	}
	cout << "These String is  not equal!\n";
	return true;

}

//==运算符重载
bool operator==(String &str1, String &str2)
{

	if (!strcmp(str1.data, str2.data))
	{
		cout << "These String is equal!\n";
		return true;
	}
    cout << "These String is  not equal!\n";
    return false;

}
//重载流提取运算符“>>”
istream& operator>> (istream &in, String &str)//is是cin的引用,cin是类istream的对象
{
	cout << "Please input string:(end of 'ctrl+Z')  ";
	char c[101] = { 0 };//缓冲区为100byte大小
	char ch = 0;
	int i(0);//等价于 i=0;
	while ( in>> ch  )
	{
		c[i] = ch;
		i++;
	}
	delete[]str.data;
	str.data = new char[i + 1];
	strcpy(str.data, c);

	return in;

}
//重载流插入运算符“ << ”
ostream& operator<< (ostream &out, String &str)//is是cout的引用,cout是类ostream的对象
{

	out<< str.data;
	return out;

}

 bool operator>(String &str1, String &str2)
{
	if (strcmp(str1.data, str2.data) == 1)
	{
		cout << "First String is big!";
		return true;
	}
	cout << "Second String is big!";
	return false;
}
 bool operator<(String &str1, String &str2)
{
	if (strcmp(str1.data, str2.data) == 1)
	{
		cout << "First String is big!\n";
		return false;
	}
	cout << "Second String is big!\n";
	return true;

}
//析构函数
String::~String()
{
	cout << "Free String!" << this << "\n";
}

时间: 2024-10-18 17:43:34

String类的实现与思考的相关文章

深入分析Java的String类的方法与特点

字符串是任何编程语言都必须支持的变量类型,有些编程语言是直接提供了原生的变量类型,有些编程语言则使用语法特性以 SDK 的形式提供支持.在Java编程平台中,对字符串的支持使用了后者的形式,就是通过在 JDK中提供一个名为String的类,对应字符串这个变量类型. 源码分析 既然JDK中的String类对应了字符串变量类型,为了熟练地掌握Java中字符串相关的技能,我们必须深入地分析和研究一下这个类.编码界有一句名言叫做 "源码面前,了无秘密",因此,我们第一步就是来看看String类

JDK源码学习--String篇(二) 关于String采用final修饰的思考

JDK源码学习String篇中,有一处错误,String类用final[不能被改变的]修饰,而我却写成静态的,感谢CTO-淼淼的指正. 风一样的码农提出的String为何采用final的设计,阅读JDK源码的时候,有粗略的思考过,今天下班后又把<Thinking in Java>中关于final的内容重新看了一遍,对此写下一些关于自己的理解和想法. String类中final关键字的使用 final关键字,用来描述一块数据不能被改变,两种可能理由:设计.效率 final使用的三种情况:数据.方

关于Emit中动态类型TypeBuilder创建类标记的一点思考

  利用TypeBuilder是可以动态创建一个类型,现在有个需求,动态生成一个dll,创建类型EmployeeEx,需要继承原dll里面的Employee类,并包含Employee类上的所有类标记.   网上有很多例子, //创建TypeBuilder. TypeBuilder myTypeBuilder = myModBuilder.DefineType(typeName, TypeAttributes.Public); myTypeBuilder.SetParent(type);   大概

Java面试准备之String类专项突破+源码分析

String的源码中有很多Arrays的方法使用,建议先参阅Arrays的类库 基本介绍: String是一个比较特殊的类,有很多种建立的方法. 如果使用传统的构造方法比如 String s = new String("字符串");这时的对象会在堆上分配,这时候比较两个字符串地址就不相等,而用""双引号包起来的内容会在常量池中做停留,这时如果有两个内容一样的地址就一样了. 因此,使用==来比较字符串是不靠谱的. String类还实现了三个接口:Serializabl

String类的疑惑

Java String类的疑惑: 创建 拼接 String是java的常用类之一,本质是字符数组char[].String类是final类,不可被继承.关于String的创建,可以通过new来创建对象,也可以直接赋值.但是这两种创建方式的实现机制是不同的.提到对象的创建,我们就会想到堆.栈,这里还有一个string pool的概念,JVM维护一个String池,池中的string对象不可重复,string池不属于堆栈,而是一个常量池. 一.创建 创建一个String对象,主要有两种方式: Str

java基础复习:final,static,以及String类

2.final 1)为啥String是final修饰的呢? 自己答: 答案: 主要是为了“效率” 和 “安全性” 的缘故.若 String允许被继承, 由于它的高度被使用率, 可能会降低程序的性能,所以String被定义成final. 还有另一个解释: 带有final修饰符的类是不可派生的.在Java核心API中,有许多应用final的例子,例如java.lang.String.为String类指定final防止了人们覆盖length()方法. 另外,如果指定一个类为final,则该类所有的方法

java中String类为什么不可变?

在面试中经常遇到这样的问题:1.什么是不可变对象.不可变对象有什么好处.在什么情景下使用它,或者更具体一点,java的String类为什么要设置成不可变类型? 1.不可变对象,顾名思义就是创建后的对象不可以改变,典型的例子有java中的String类型. 2.相比于可变对象,不可变对象有很多优势: (1)不可变对象可以提高String Pool(字符串常量池)的效率和安全性.如果你知道一个对象是不可变动 ,那么需要拷贝的对象的内容时就不用复制它本身二只是复制它的地址,复制地址(通常一个指针的大小

String类的使用细节

String类的特点: 字符串对象一旦被初始化就不会被改变,字符串存储在字符串常量池中(字符串缓冲区).如果池中没有就创建,如果有就直接拿过来用. 代码验证如下: String s = "abc";//在常量池中创建了一个字符串对象 String s1 = "abc";//true //s与s1内容相同,地址相同 System.out.println(s==s1);//true System.out.println(s==s1);//true String s2 =

java里String类为何被设计为final

前些天面试遇到一个非常难的关于String的问题,"String为何被设计为不可变的"?类似的问题也有"String为何被设计为final?"个人认为还是前面一种问法更准确,设计成final仅仅保证了String类不能被继承,而Immutable相对于final要严格的多. 下文主要翻译自:http://java67.blogspot.sg/2014/01/why-string-class-has-made-immutable-or-final-java.html