728x90
반응형
	str3 = str1 + str2;
	str4 = str1 + "World";
	str5 = "AAA" + str1;

객체 + 객체가 있고, 객체 + 문자열이 있기 때문에 두가지로 만들어줬다.

CMyString operator+(CMyString& _pBuff)
	{
		char* pTemp = new char[strlen(m_pBuff) + strlen(_pBuff.m_pBuff) + 1]; 
        
		strcpy_s(pTemp, strlen(m_pBuff) + strlen(_pBuff.m_pBuff) + 1, m_pBuff);
		strcat_s(pTemp, strlen(m_pBuff) + strlen(_pBuff.m_pBuff) + 1, _pBuff.m_pBuff);

		return CMyString(pTemp);
	}
CMyString operator+(char* _rBuff)
	{
		char* pTemp = new char[strlen(m_pBuff) + strlen(_rBuff) + 1];
        
		strcpy_s(pTemp, strlen(m_pBuff) + strlen(_rBuff) + 1, m_pBuff);
		strcat_s(pTemp, strlen(m_pBuff) + strlen(_rBuff) + 1, _rBuff);

		return pTemp;
	}

strlen(m_pBuff) + strlen(_pBuff.m_pBuff) + 1

-> 이 부분에서 +1은 null도 포함해야하기 때문

 

연산자 오버로딩은 좌측 객체의 operator를 호출한다!

문자열 + 객체는 위치가 바꼈기 때문에 교환법칙을 이용해야한다.

 

-- 교환법칙

연산자 오버로딩을 전역에 구현한다.

* 인자 중 하나는 객체 타입이거나 객체의 레퍼런스 타입이 와야한다!

 (레퍼런스를 사용하는 이유 : 복사생성자의 연산을 줄이기 위해)

 

CMyString operator+(char* _pName, CMyString& _rBuff)
{
	char* pTemp5 = new char[strlen(_pName) + strlen(_rBuff.Get_Buff()) + 1];
	strcpy_s(pTemp5, strlen(_pName) + strlen(_rBuff.Get_Buff()) + 1, _pName);
	strcat_s(pTemp5, strlen(_pName) + strlen(_rBuff.Get_Buff()) + 1, _rBuff.Get_Buff());


	return pTemp5;
}

나는 이런식으로 위의 operator+함수와 동일한 방식으로 구현했다.

하지만, 더 간단하게 이렇게 할 수 있다.

CMyString operator+(char * _pName, CMyString & _pBuff)
{

	return CMyString(_pName) + _pBuff;			
}

임시객체를 이용하여 리턴한다.

(임시객체는 코드라인을 벗어나면 소멸하기 때문에 자주 사용한다.)

이 때, 객체의 위치가 바뀌지 않도록 주의해야한다. 아니면 문자의 위치가 바뀔 수 있음.

(AAAHello가 출력되야하는데 HelloAAA가 출력되는 상황이 생긴다...)

 

여기서 operator+ 함수만 만들면 안된다. 객체 = 객체 + 객체 이기 때문에 = 연산자도 필요하다!

=연산자 오버로딩을 구현하지 않아서 계속 오류가 생겼었다.. 

 

	CMyString operator=(const CMyString& _rBuff)
	{
		m_pBuff = new char[strlen(_rBuff.m_pBuff) + 1];
		strcpy_s(m_pBuff, strlen(_rBuff.m_pBuff) + 1, _rBuff.m_pBuff);
		return *this;
	}
	CMyString operator=(char* _rBuff)
	{
		m_pBuff = new char[strlen(_rBuff) + 1];
		strcpy_s(m_pBuff, strlen(_rBuff) + 1, _rBuff);
		return *this;    // 나 자신이 반환되야하기 때문에 역참조 this 포인터 사용
	}

이렇게 코드를 작성했는데 여기에서 동적할당을 하기 전에 객체가 대입 될 예정이니 나 자신(m_pBuff)은 필요없기 때문에 동적할당을 해제해주는 것이 좋다. (null값이 됨!)


 객체(나) = 객체(나) + 객체이다. 어쨌든 객체(나)는 값이 변하게된다. 함수가 종료되어도 나는 메모리에서 소멸하지 않아야 해서 반환타입에 레퍼런스!!를 붙여주는 것이 좋다.
 -> 연산 속도를 높이기 위해. 내가 소멸되어도(함수가 종료되어도) 복사된 놈은 살아있음, 지역 변수가 반환되면 그냥 반환타입~

 

여기서 기억해야 할

<<< 복사 생성자의 호출 시점 3가지 >>>
1. 먼저 생성한 객체를 나중에 생성하는 객체의 생성자로 전달하는 경우
2. 함수의 매개 변수로 객체가 전달되는 경우
3. 함수의 반환 타입으로 객체가 반환되는 경우

 

이제 출력 해보면

이렇게 출력된다.

	str1 += str2;
	str2 += "World";
    	str3 = str1;
	str4 = "World";

+=연산은 누적 연산이다. 즉, =연산자와 마찬가지로 나 자신이 반환되어야한다. 그래서 반환타입에 레퍼런스를 사용하는게 좋다.

CMyString operator+=(CMyString& _pBuff)
	{
		strcat_s(m_pBuff, strlen(m_pBuff) + strlen(_pBuff.m_pBuff) + 1, _pBuff.m_pBuff);

		return CMyString(m_pBuff);
	}
CMyString operator+=(char* _rBuff)
	{
		strcat_s(m_pBuff, strlen(m_pBuff) + strlen(_rBuff) + 2, _rBuff);

		return CMyString(m_pBuff);
	}

여기는 왜 동적할당을 안했었는지 모르겠지만........ 이렇게 코드를 짰었는데 여기도 동적할당을 해줘야한다. (깊은복사)

======> 오류발생!!!!

	CMyString& operator+=(CMyString& _pBuff)
	{
		char* pTemp = new char[strlen(m_pBuff) + strlen(_pBuff.m_pBuff) + 1];

		strcpy_s(pTemp, strlen(m_pBuff) + strlen(_pBuff.m_pBuff) + 1, m_pBuff);
		strcat_s(pTemp, strlen(m_pBuff) + strlen(_pBuff.m_pBuff) + 1, _pBuff.m_pBuff);

		return *this;
	}
	CMyString& operator+=(char* _rBuff)
	{
		char* pTemp = new char[strlen(m_pBuff) + strlen(_rBuff) + 1];

		strcpy_s(pTemp, strlen(m_pBuff) + strlen(_rBuff) + 1, m_pBuff);
		strcat_s(pTemp, strlen(m_pBuff) + strlen(_rBuff) + 1, _rBuff);

		return *this;
	}

=============> 깊은 복사가 되도록 수정했다!!!! 

출력 후

	cout << (str1 == str2) << endl;
	cout << ("AAA" == str1) << endl;
int operator==(CMyString& _pBuff)
	{
		if (strcmp(m_pBuff, _pBuff.m_pBuff) == 0)
				return 1;	//참
		return 0;	// 거짓
	}

이런식으로 코드를 짰지만 간단하게 아래와 같은 방법도 있다.

bool CMyString::operator==(CMyString & _String)
{
	return !strcmp(m_pString, _String.m_pString);   // 참이면 0 , 거짓이면 0아닌 값 반환
}

bool CMyString::operator==(char * _pStr)
{
	return !strcmp(m_pString, _pStr);
}

==연산도 마찬가지로 교환법칙이 필요하다!

int operator==(char* _rBuff, CMyString& _pBuff)
{
	if (strcmp(_rBuff, _pBuff.Get_Buff()) == 0)
			return 1;	//참
	return 0;	// 거짓
}
bool operator==(char * _pStr, CMyString & _string)
{
	return _string == _pStr;
}

==연산은 단순비교이기 때문에 객체의 위치가 바껴도 상관없다!!

 

이 과정들을 해보니 연산자 오버로딩을 좀 더 이해하게 된듯하다. 하지만 아직은 더 연습이 필요할듯.

string 다른 기능도 구현해봐야지..

728x90
반응형

'c++ > c++' 카테고리의 다른 글

알고리즘 - for_each  (0) 2021.05.29
STL - vector container  (0) 2021.05.26
STL(Standard Template Library)  (0) 2021.05.23
연산자 오버로딩 - string class 구현1  (0) 2021.05.22
const와 포인터  (0) 2021.05.22

+ Recent posts