MFC CString类的函数实现原理

在MFC框架中,CString类用的很多,它是对原来标准c中字符串类型的一种包装,因为里面有两个成员变量char* m_pData和int m_nLength来维护这个类。

对于成员函数:

1、几个默认的构造函数

CString(); //缺省构造

CString( const CString& stringSrc );
//拷贝构造

CString( const char* lpsz );
//根据字符串常量初始化

CString( char ch, int nRepeat = 1);
//串内有n个ch字符

CString(const char* cstr,int nLength);
//根据字符串常量的一部分

实现函数:

CString::CString()
{
	//m_pData = new char;
	//m_pData[0] = 0
	m_pData = new char(0);//new一个字符串 并且等于0
	m_nLength = 0;
}
//拷贝构造发生的条件是:当用一个已有的对象作为初始化数据构造一个新对象时
CString::CString( const CString& str )	//拷贝构造
{
	m_nLength = str.m_nLength;

	//由于是拷贝构造,不需要删除原来的空间
	//申请内存空间
	m_pData = new char[m_nLength+1];

	//m_pData = str.m_pData;//浅拷贝

	strcpy(m_pData,str);//深拷贝

}

CString::CString( const char* lpsz )		//根据字符串常量初始化
{
	m_nLength = strlen(lpsz);

	//申请空间
	m_pData = new char[m_nLength + 1];
	strcpy(m_pData,lpsz);
}

CString::CString( char ch, int nRepeat)	//串内有n个ch字符
{
	m_nLength = nRepeat;
	m_pData = new char[m_nLength+1];

	m_pData[m_nLength] = '\0';//最后一个字符表示为0;
	int i = m_nLength;
	while(i--)
	{
		m_pData[i] = ch;
	}
}

CString::CString(const char* cstr,int nLength)//根据字符串常量的一部分
{
	//m_nLength = nLength;
	//m_pData = new char[nLength+1];
	//strncpy(m_pData,cstr,nLength);//函数根据长度进行拷贝
	m_nLength = strlen(cstr);
	m_nLength = m_nLength>nLength ? nLength:m_nLength;
	m_pData = new char[m_nLength+1];
	m_pData[m_nLength] = '\0';
	int i =0;
	while(i<m_nLength)
		m_pData[i] = cstr[i++];

}

2、赋值操作函数

CString& operator=(const char* cstr) ;
//删除已有文字的堆空间,重新分配

CString& operator=(const CString &str);
//删除已有文字的堆空间,重新分配

<span style="font-size:18px;">//重载赋值操作
CString& CString::operator=(const char* cstr) 	//删除已有文字的堆空间,重新分配
{
	int nLen = strlen(cstr);
	if (nLen>m_nLength)
	{
		//删除已有的堆空间
		delete []m_pData;
		m_pData = new char[m_nLength+1];
	}
	//m_pData = cstr;//浅拷贝
	m_nLength = nLen;
	strcpy(m_pData,cstr);
	return *this;

}
CString& CString::operator=(const CString &str)	//删除已有文字的堆空间,重新分配
{
	int nlen = str.m_nLength;
	if (nlen > m_nLength)
	{
		//删除已有长度
		delete []m_pData;
		m_pData = new char[nlen + 1];
	}

	m_nLength = nlen;
	strcpy(m_pData,str.m_pData);

	return *this;
}</span>

3、类型转化

	//类型转化
	operator const char* () const
	{
		return m_pData;
	}
	//凡是单行函数放在头文件中,编译器会自动使用inline内联格式编译
	char operator []( int nIndex ) const	//获取串内上的某个字符
	{
		return m_pData[nIndex];
	}

4、友元函数

	friend bool operator!=(const CString& str1,const CString& str2) ;
	friend bool operator==(const CString& str1,const CString& str2) ;
	friend bool operator<(const CString& str1, const CString& str2) ;
	friend bool operator>(const CString& str1,  const CString& str2) ;

<pre name="code" class="html">//友元
bool operator!=(const CString& str1,const CString& str2)
{
	return strcmp(str1,str2) != 0;
}
bool operator==(const CString& str1,const CString& str2)
{
	return !strcmp(str1,str2);
}
bool operator<(const CString& str1, const CString& str2)
{
	return strcmp(str1,str2)<0;
}
bool operator>(const CString& str1,  const CString& str2)
{
	return strcmp(str1,str2)>0;
}

5、查找替换函数

CString CString::Mid( int nFirst ) const
{
	return Mid(nFirst,m_nLength - nFirst);
}

//原字符串不变
//需要进行条件判断
CString CString::Mid( int nFirst, int nCount ) const
{
	CString str;
	if (nFirst<0)
	{
		nFirst = 0;
	}
	if (nCount <= 0 || nFirst > m_nLength -1)
	{
		return str;//直接返回空字符串
	}

	//在中间区域
	int nLen = m_nLength - nFirst;
	//如果nlen 比ncount大,则拷贝nfirst后面的所有字符
	nLen = nLen < nCount ? nLen:nCount;

	//释放原有的空间,一个字节
	delete []str.m_pData;//重要
	str.m_pData = new char[nLen+1];
	//逐一拷贝
	str.m_nLength = nLen;
	str.m_pData[nLen] = '\0';
	while(nLen--)
	{
		str.m_pData[nLen] = m_pData[nFirst+nLen];
	}

	//为什么会触发构造函数,,?
	return str;

}
//
CString CString::Left( int nCount ) const
{
	return Mid(0,nCount);
}

void CString::MakeUpper( )
{
	int i = m_nLength;
	while(i--)
	{
		m_pData[i] = _toupper(m_pData[i]);
	}

	//也可以用
	//_strupr(m_pData);直接转化
}
void CString::MakeLower( )
{
	_strlwr(m_pData);
}
void CString::MakeReverse( )
{
	//int i = 0,j = m_nLength-1;
	//char c;
	//while(i<j)
	//{
	//	c = m_pData[i];
	//	m_pData[i] = m_pData[j];
	//	m_pData[j] = c;
	//	++i;
	//	++j;
	//}

	int i = 0,j = m_nLength;
	char c;
	char *p = m_pData;
	char *q = m_pData+m_nLength-1;
	while(p<q)
	{
		c = *p;
		*p = *q;
		*q = c;
		++p;
		--q;
	}
}

int CString::Replace( char chOld, char chNew )
{
	int i = m_nLength;
	int nCount = 0;
	while(i--)
	{
		if (m_pData[i] == chOld)
		{
			m_pData[i] = chNew;
			++nCount;
		}
	}
	return nCount;
}

int CString::Find( char ch ) const
{
	int i = 0;
	while(i<m_nLength)
	{
		if (m_pData[i] == ch)
		{
			return i;
		}
		++i;
	}
	return -1;
}

//int CString::Find( const char* lpszSub ) const
//{
//
//}
//int CString::Find( char ch, int nStart ) const
//{
//
//}
int CString::Find( const char* pstr, int nStart ) const
{
	//字串比较
	if (nStart>=m_nLength)
	{
		return -1;
	}
	char *p = strstr(m_pData+nStart,pstr);
	return p-m_pData;//返回的索引是基于首地址的
}

int CString::ReverseFind( char ch ) const
{
	int i = m_nLength;
	while(i--)
	{
		if (m_pData[i] == ch)
		{
			return i;
		}
	}
	return -1;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-28 19:28:30

MFC CString类的函数实现原理的相关文章

CString转换成int CString类相应函数

CString 型转化成 int 型 把 CString 类型的数据转化成整数类型最简单的方法就是使用标准的字符串到整数转换例程. 虽然通常你怀疑使用_atoi()函数是一个好的选择,它也很少会是一个正确的选择.如果你准备使用 Unicode 字符,你应该用_ttoi(),它在 ANSI 编码系统中被编译成_atoi(),而在 Unicode 编码系统中编译成_wtoi().你也可以考虑使用_tcstoul()或者_tcstol(),它们都能把字符串转化成任意进制的长整数(如二进制.八进制.十进

vc控制台程序中如何使用cstring类的函数,头文件怎么包含?

1.project->setting->general 里的Microsoft Foundmation class选择“Use MFC in a Shared DLL”,再包含<afx.h>就行了.2.直接include <afx.h>3.#include <atlstr.h>

VS2010-MFC(MFC常用类:CString类)

转自:http://www.jizhuomi.com/software/228.html CString类简介 CString类作为MFC的常用类,当之无愧.可以这样说,只要是从事MFC开发,基本都会遇到使用CString类的场合.因为字符串的使用比较普遍,而CString类又提供了对字符串的便捷操作,所以它给MFC开发人员带来了高的开发效率,受到了开发者的欢迎. 大家使用VS2010的话,可能会见到CStringT,实际上它是一个操作可变长度字符串的模板类.CStringT模板类有三个实例:C

MFC浅析(7) CWnd类虚函数的调用时机、缺省实现

CWnd类虚函数的调用时机.缺省实现 FMD(http://www.fmdstudio.net) 1. Create 2. PreCreateWindow 3. PreSubclassWindow 4. PreTranslateMessage 5. WindowProc 6. OnCommand 7. OnNotify 8. OnChildNotify 9. DefWindowProc 10. DestroyWindow 11. PostNcDestroy CWnd作为MFC中最基本的与窗口打交

类虚函数表原理实现分析(当我们将虚表地址[n]中的函数替换,那么虚函数的实现就由我们来控制了)

原理分析 当调用一个虚函数时, 编译器生成的代码会调用 虚表地址[0](param1, param2)这样的函数. 已经不是在调用函数名了. 当我们将虚表地址[n]中的函数实现改为另外的函数, 虚函数的实现就由我们来控制了. 实验 根据虚表原理, 实验一下修改自己程序的虚函数表项地址. 使编译器生成的代码执行一个虚函数A时, 执行的是我们自己定义的非虚函数B. 知识点 * 使用union赋值, 绕过编译器函数与变量强转赋值的限制 * 类成员函数指针的执行 * 修改和恢复自己的代码段属性 * 虚函

关于虚函数,类的内存分布以及类的成员函数调用原理

1.类的内存分布 空类为了占位,空间占一个字节 成员函数,静态函数,静态变量并不占内存(不和类放在一起) 所有的虚函数也并不和类放在一起,而是将所有的虚函数构造成一个虚函数表,用一个指针指向这个虚函数表,类仅仅存储这个指针,一个指针在32位的机器上占四个字节 所有的非静态成员变量占内存 因此,类的内存分布=所有的非静态成员变量+虚指针(自创的名词:即指向虚函数表的指针) 2.虚函数的原理 一个非继承的类:一个虚指针(指向他的虚函数表). 一个单继承的类:一个虚指针(指向他的虚函数表,这个虚函数表

非MFC的DLL中使用CString类

1.头文件添加 /* 非MFC DLL中使用CString */ #define _AFXDLL #include <afx.h> 注意:要定义在 #include<windows.h>之前,否则会报错 2.cpp 文件中添加 /* 非MFC DLL中使用CString */ // The following symbol used to force inclusion of this module for _USRDLL #ifdef _X86_ extern "C&q

C++中虚函数工作原理和(虚)继承类的内存占用大小计算

一.虚继承情况下类的内存大小计算 当每个基类中有多个虚函数时,并且在虚继承的情况下,内存是如何分配的,如何计算类的大小,下面举例说明: #include<iostream> using namespace std; class A { public: int a; virtual void aa(){}; }; class D { public: virtual void dd(){}; }; class C { public: virtual void cc(){}; }; class B

CString中Format函数与格式输入与输出

CString中Format函数与格式输入与输出 Format是一个很常用,却又似乎很烦的方法,以下是它的完整概貌,以供大家查询之用: 格式化字符串forma("%d",12)意思是将一个整形的格式化的字符(我认为是保持其形状不变) 1).格式说明总是以%字符开始,以下是不同类型数据的格式方式%号后的说明: d输出带符号十进制数 o输出无符号八进制数 x输出无符号十六进制数 u输出无符号数 c输出单个字符 s输出一串字符 f输出实数(6位小数) e以指数形式输出实数 g选用f与e格式中