25.07.30 개발학습일지 / C++ Study4(chapter 5, chapter 6)

2025. 7. 30. 22:52·LMS 7/개발일지

https://marin0806.tistory.com/80

 

25.07.29 학습개발일지 / C++ Study4

과제1. C++ 문제 04-11) 원본 코드// FruitSaleSim1.cpp#include using namespace std;class FruitSeller{private: int APPLE_PRICE; int numOfApples; int myMoney; public: void InitMembers(int price, int num, int money) { APPLE_PRICE=price; numOfApples=num;

marin0806.tistory.com

 


chapter 05 . 복사 생성자

1. 기본 구조

#include<iostream>
#include<cstring>
using namespace std;

class Person
{
	private:
		char*name;
		int age;
	public:
		// 생성자
		Person(~, ~) : ~ {}
		// 복사 생성자
		Person(const Person &copy)
			: age(copy.age) // 멤버 대 멤버 복사(얕은 복사)
		{
			name = new char[strlen(copy.name) + 1]; // 동적 할당(깊은 복사)
			strcpy(name, copy.name);
		}
		// 소멸자
		~Person()
		{
			delete[] name;
		}
};

2. 메모리 공간의 할당 및 초기화(일반 변수를 통한)

1) 대표적인 상황

int num1 = num2;

 

2) 매개변수를 통한 상황

#include<iostream>
using namespace std;

int SimpleFunc(int n){
	~
}

int main(void){
	int num;
	SimpleFunc(num);
	~
}

>

int n(함수 매개변수) = num;

 

3) 함수 반환 값을 통한 상황

#include<iostream>
using namespace std;

int SimpleFunc(int n){
	~
	return n;
}

int main(void){
	int num;
	SimpleFunc(num);
	~
}

>

SimpleFunc(num) : int temp(별도의 메모리 공간) = n; (return한 n이 초기화 되는 과정)


3. 메모리 공간의 할당 및 초기화(객체와 복사 생성자를 통한)

1) 비교

// 첫번째 상황
SoSimple obj2 = obj1;
또는
SoSimple obj2(obj1);

 

// 두번째 상황
#include<iostream>
using namespace std;

// SoSimple형 객체를 매개변수로 하고, SoSimple형을 반환하는 함수
SoSimple SimpleFuncObj(SoSimple ob){
	~
}
int main(void){
	SoSimple obj;
	SimpleFuncObj(obj);
}

>

SoSimple ob = obj; (복사 생성자 호출)

 

// 세번째 상황
#include<iostream>
using namespace std;

// 클래스 정의 함수
SoSimple SimpleFuncObj(SoSimple ob){
	~
	return ob;
}
int main(void){
	SoSimple obj;
	SimpleFuncObj(obj);
}

>

SoSimple ob = obj; (복사 생성자 호출 1)

SoSimple temp(임시, 사용하지 않으면 사라짐) = obj; (복사 생성자 호출 2)

​

2) 실제 코드를 보며 분석하기

#include <iostream>
using namespace std;

class SoSimple
{
private:
	int num;
public:
	SoSimple(int n) : num(n)
	{  }
	SoSimple(const SoSimple& copy) : num(copy.num)
	{
		cout<<"Called SoSimple(const SoSimple& copy)"<<endl;
	}
	void ShowData()
	{
		cout<<"num: "<<num<<endl;
	}
};
	
void SimpleFuncObj(SoSimple ob)
{
	ob.ShowData();
}

int main(void)
{
	SoSimple obj(7);
	cout<<"함수호출 전"<<endl;
	SimpleFuncObj(obj);
	cout<<"함수호출 후"<<endl;
	return 0;
}

>

main의 구조

1. obj 객체의 num을 생성자를 통해 7로 초기화하며 선언

2. SimpleFuncObj 함수에서 SoSimple ob = obj; 로 초기화, ob의 복사 생성자를 호출하여 obj 객체에 복사한다

2-1. 함수 내 함수 호출은 ob 객체를 대상으로 하지만 obj는 ob의 복사본으로 실질적으로 영향을 주지 않는다

 

#include <iostream>
using namespace std;

class SoSimple
{
private:
	int num;
public:
	SoSimple(int n) : num(n)
	{ }
	SoSimple(const SoSimple& copy) : num(copy.num)
	{
		cout<<"Called SoSimple(const SoSimple& copy)"<<endl;
	}
	SoSimple& AddNum(int n)
	{
		num+=n;
		return *this;
	}
	void ShowData()
	{
		cout<<"num: "<<num<<endl;
	}
};

SoSimple SimpleFuncObj(SoSimple ob)
{
	cout<<"return 이전"<<endl;
	return ob;
}

int main(void)
{
	SoSimple obj(7);
	SimpleFuncObj(obj).AddNum(30).ShowData();
	obj.ShowData();
	return 0;
}

>

main의 구조

1. obj 객체의 num을 생성자를 통해 7로 초기화하며 선언

​

2. SoSimple ob = obj; : obj를 ob에 복사

3. return ob; -> SoSimple temp(임시객체) = ob : ob를 temp에 복사

3-1. 결과적으로 temp1.AddNum(30).ShowData() 와 같다

4. AddNum(30)

: temp1(임시객체)의 멤버변수 num에 30을 더 한다

: 반환시 -> SoSimple &temp2(임시객체를 참조하는 참조자) = *this

(this는 SoSimple* 형으로 현재 객체의 주소를 뜻하므로 *this로 역참조를 해야함)

4-1. temp1(임시객체).temp2(임시참조자).ShowData() 와 같아진다

5. temp1 객체의 메서드 void ShowData()를 실행함

​

6. obj 객체의 메서드 void ShowData()를 실행함

​

결과가 이렇게 나온 이유는

첫번째 num은 temp1 객체의 num이고

두번째 num은 obj 객체의 num이기 때문이다


4. 임시객체

1) 임시객체 확인하기

#include <iostream>
using namespace std;

class Temporary
{
private:
	int num;
public:
	Temporary(int n) : num(n)
	{
		cout<<"create obj: "<<num<<endl;
	}
	~Temporary()
	{
		cout<<"destroy obj: "<<num<<endl;  
	}
	void ShowTempInfo()
	{
		cout<<"My num is "<<num<<endl;
	}
};

int main(void)
{
	Temporary(100);
   Temporary(200).ShowRempInfo()
}

>

main을 보면

객체를 생성하지 않고 바로 생성자를 통해 초기화하려는 모습이 보이는데

이는 정상적으로 진행이되며, 여기서 임시객체가 생성이 된다

​

2) 임시객체는 사실

(임시객체의 참조 값).ShowTempInfo()

>

임시객체는 메모리에 존재하고

실제로 코드 상에서는 참조 값이 반환되어

객체처럼 쓰일 수 있다

 

#include <iostream>
using namespace std;

class SoSimple
{
private:
	int num;
public:
	SoSimple(int n) : num(n)
	{
		cout<<"New Object: "<<this<<endl;
	}
	SoSimple(const SoSimple& copy) : num(copy.num)
	{
		cout<<"New Copy obj: "<<this<<endl;
	}
	~SoSimple()
	{
		cout<<"Destroy obj: "<<this<<endl;
	}
};

SoSimple SimpleFuncObj(SoSimple ob)
{
	cout<<"Parm ADR: "<<&ob<<endl;
	return ob;
}

int main(void)
{
	SoSimple obj(7);
	SimpleFuncObj(obj);

	cout<<endl;
	SoSimple tempRef=SimpleFuncObj(obj);
	cout<<"Return Obj "<<&tempRef<<endl;
	return 0;
}

>

main의 구조

1. SoSimple obj : obj를 생성자를 통해 7로 초기화하여 선언(New Object)

2. SimpleFuncObj(obj);

: ob를 obj로 복사(New Copy obj)

: return ob > ob를 임시객체에 복사(New copy obj) 후 return / ob는 함수와 함께 소멸(Destroy obj)

: 사용하지 않으므로 임시객체 소멸(Destroy obj)

3. count << endl;

4. SoSimple tempRef = SimpleFuncObj(obj);

: ob를 obj로 복사(New copy obj)

: return ob > ob를 임시객체 복사(New copy obj) 후 return / ob는 함수와 함께 소멸(Destroy obj)

: 임시객체에 tempRef 라는 이름 부여(tempRef는 새로 객체가 생성되지 않음)

5. cout << "Return Obj " << &tempRef << endl;

: tempRef 객체의 주소 출력


5. 문제(p.226)

#include<iostream>
#include<cstring>
using namespace std;

// 조건 enum을 사용하여 직급을 정의
// main의 COMP_POS::enum을 위해 namespace를 사용
namespace COMP_POS {
    enum {CLERK=1, SENIOR, ASSIST, MANAGER};
}

class NameCard{
    private:
        char*name; // 이름
        char*company; // 회사
        char*phone; // 전화번호
        int rank; // 입력받은 enum에 의한 정수를 저장
        char*rankName; // switch문을 통해 직급 이름을 저장
    public:
        // 생성자, 멤버 이니셜라이저를 사용하여 먼저 초기화 후 입력받은 값을 차례대로 저장
        NameCard(const char* input_name, const char* input_company, const char* input_phone, int rank)
            : name(), company(), phone(), rank(rank) {
            name = new char[strlen(input_name) + 1];
            strcpy(name, input_name);
            company = new char[strlen(input_company) + 1];
            strcpy(company, input_company);
            phone = new char[strlen(input_phone) + 1];
            strcpy(phone, input_phone);
            rankName = new char[20];
            switch (rank){
                case COMP_POS::CLERK:
                    rank = COMP_POS::CLERK;
                    strcpy(rankName, "사원");
                    break;
                case COMP_POS::SENIOR:
                    rank = COMP_POS::SENIOR;
                    strcpy(rankName, "대리");
                    break;
                case COMP_POS::ASSIST:
                    rank = COMP_POS::ASSIST;
                    strcpy(rankName, "주임");
                    break;
                case COMP_POS::MANAGER:
                    rank = COMP_POS::MANAGER;
                    strcpy(rankName, "보조자");
            } // switch(rank)
        } // NameCard(const char* input_name, ...)
        NameCard(const NameCard& copy)
            : rank(copy.rank){
            name = new char[strlen(copy.name) + 1];
            strcpy(name, copy.name);
            company = new char[strlen(copy.company) + 1];
            strcpy(company, copy.company);
            phone = new char[strlen(copy.phone) + 1];
            strcpy(phone, copy.phone);
            rankName = new char[strlen(copy.rankName) + 1];
            strcpy(rankName, copy.rankName);
        } // NameCard(const NameCard& copy)
        // 직급 이름을 출력하는 함수
        void ShowNameCardInfo() const{
            cout << "이름: " << name << endl;
            cout << "회사: " << company << endl;
            cout << "전화: " << phone << endl;
            cout << "직급: " << rankName << endl;
            cout << endl;
        }
        ~NameCard() {
            delete[] name;
            delete[] company;
            delete[] phone;
            delete[] rankName; // 동적 할당된 메모리 해제
        }
};

int main(void){
    NameCard manClerk("Lee", "ABCEng", "010-1111-2222", COMP_POS::CLERK);
    NameCard copy1 = manClerk;
    NameCard manSenior("Hong", "OrangeEng", "010-3333-4444", COMP_POS::SENIOR);
    NameCard copy2 = manSenior;
    copy1.ShowNameCardInfo();
    copy2.ShowNameCardInfo();
    return 0;
}

Chapte 06. friend / static / const

1. friend

> friend로 객체를 선언시 해당 클래스의 private 멤버에 접근할 수 있다

 

1) 클래스에 대해 friend 선언

#include <iostream>
#include <cstring>
using namespace std;

class Girl;

class Boy
{
private:
	int height;
	friend class Girl; // 클래스 Girl에 대한 friend 선언
public:
	Boy(int len) : height(len)
	{ }
	void ShowYourFriendInfo(Girl &frn);
};

class Girl
{
private:
	char phNum[20];
public:
	Girl(char * num)
	{
		strcpy(phNum, num);
	}
	void ShowYourFriendInfo(Boy &frn);
	friend class Boy; // 클래스 Boy에 대한 friend 선언
};

// Boy 클래스의 멤버함수임에도 Girl 클래스의 private 멤버변수 phNum에 접근
void Boy::ShowYourFriendInfo(Girl &frn)
{
	cout<<"Her phone number: "<<frn.phNum<<endl;
}

// Girl 클래스의 멤버함수임에도 Boy 클래스의 private 멤버변수 height에 접근
void Girl::ShowYourFriendInfo(Boy &frn)
{
	cout<<"His height: "<<frn.height<<endl;
}

int main(void)
{
	Boy boy(170);
	Girl girl("010-1234-5678");

	boy.ShowYourFriendInfo(girl);
	girl.ShowYourFriendInfo(boy);
	return 0;
}

 

2) friend 선언 확장

> friend는 클래스 멤버함수와 일반함수를 대상으로도 선언이 가능

#include <iostream>
using namespace std;

class Point;

class PointOP
{
private:
	int opcnt;
public:
	PointOP() : opcnt(0)
	{  }

    // 반환형이 Point인 멤버함수
	Point PointAdd(const Point&, const Point&);
	Point PointSub(const Point&, const Point&);

	~PointOP()
	{
		cout<<"Operation times: "<<opcnt<<endl;
	}
};

class Point
{
private:
	int x; 
	int y;    
public:
	Point(const int &xpos, const int &ypos) : x(xpos), y(ypos)
	{  }

    // PointOp의 멤버함수들에 대한 friend선언
	friend Point PointOP::PointAdd(const Point&, const Point&);
	friend Point PointOP::PointSub(const Point&, const Point&);

    // 일반함수에 대한 friend 선언
	friend void ShowPointPos(const Point&);
};


Point PointOP::PointAdd(const Point& pnt1, const Point& pnt2)
{
	opcnt++;
	return Point(pnt1.x+pnt2.x, pnt1.y+pnt2.y); // friend 선언이 되었기 때문에 PointOP의 멤버함수가 Point의 멤버변수에 접근 가능
}

Point PointOP::PointSub(const Point& pnt1, const Point& pnt2)
{
	opcnt++;
	return Point(pnt1.x-pnt2.x, pnt1.y-pnt2.y); // friend 선언이 되었기 때문에 PointOP의 멤버함수가 Point의 멤버변수에 접근 가능
}

int main(void)
{
	Point pos1(1, 2); // pos1 객체를 Point 클래스 생성자로 초기화
	Point pos2(2, 4); // pos2 객체를 Point 클래스 생성자로 초기화
	PointOP op; // op 객체를 PointOP 클래스 생성자로 초기화

    // firend 선언된 함수들로 Point 클래스의 멤버변수에 직접 접근
	ShowPointPos(op.PointAdd(pos1, pos2));
	ShowPointPos(op.PointSub(pos2, pos1));
	return 0;
}

void ShowPointPos(const Point& pos)
{
	cout<<"x: "<<pos.x<<", ";
	cout<<"y: "<<pos.y<<endl;
}

2. static

1) C언어의 static

> 전역변수의 static : 선언된 파일 내에서만 참조

 

> 함수 내 static : 한번만 초기화, 함수가 종료되어도 소멸되지 않음

2) static 멤버변수( == 클래스 변수)

> public 선언시​ C언어의 static 전역변수와 같다(클래스 네임스페이스 안에 있어 구별의 용이성이 있다.)

> private 선언시 멤버함수로만 있어 클래스 내의 전역변수로 사용 가능함

> 클래스 내 선언 / 클래스 외부에서 한 번만 초기화(정의)

> 객체의 수와 관계없이 하나만 존재한다(-> 객체가 해당 변수를 공유한다)

> 따라서 객체 없이도 접근이 가능하다(클래스명::변수명)

> 멤버변수에 접근하듯이 접근도 가능(추천하지 않는 방법, 위의 클래스 이름을 이용해서 접근하는 방법을 사용할 것)

#include <iostream>
using namespace std;

class SoSimple
{
public:
	static int simObjCnt; // static 멤버변수를 public으로 선언
public:
	SoSimple()
	{
		simObjCnt++;
	}
};
int SoSimple::simObjCnt=0; // 클래스 외부에서 한 번만 초기화

int main(void)
{
	cout<<SoSimple::simObjCnt<<"번째 SoSimple 객체"<<endl; // 객체 없이도 static 멤버변수에 접근하는 모습
	SoSimple sim1;
	SoSimple sim2;

	cout<<SoSimple::simObjCnt<<"번째 SoSimple 객체"<<endl; // 객체 없이도 static 멤버변수에 접근하는 모습
	cout<<sim1.simObjCnt<<"번째 SoSimple 객체"<<endl; // 멤버변수에 접근하는 것처럼 접근하는 모습
	cout<<sim2.simObjCnt<<"번째 SoSimple 객체"<<endl; // 멤버변수에 접근하는 것처럼 접근하는 모습
	return 0;
}

 

3) static 멤버함수

> 선언된 클래스의 모든 객체가 공유함

> public으로 선언되면 클래스 이름으로 호출이 가능함

: 따라서 객체 없이도 호출이 가능하다(클래스명::함수명())

> 객체의 멤버가 아님

: 따라서 non-static 멤버변수에 직접 접근할 수 없고, 오직 static 멤버변수에 접근이 가능함, 또한 static 멤버함수만 호출만 가능하다

4) const static 멤버

> const static 멤버변수는 선언과 동시에 초기화한다(const 멤버변수는 이니셜라이저를 통해서만 초기화가 가능했다)

 


3. mutable

> 사용하지 않는 것이 좋음

'LMS 7 > 개발일지' 카테고리의 다른 글

25.08.01 학습개발일지 C++ Study5  (2) 2025.08.01
25.07.31 학습개발일지 C++ Study5  (11) 2025.07.31
25.07.29 학습개발일지 / C++ Study4  (2) 2025.07.30
25.07.28 학습개발일지 / Makefile+  (2) 2025.07.30
25.07.27 학습개발일지 / C++ Study3  (3) 2025.07.30
'LMS 7/개발일지' 카테고리의 다른 글
  • 25.08.01 학습개발일지 C++ Study5
  • 25.07.31 학습개발일지 C++ Study5
  • 25.07.29 학습개발일지 / C++ Study4
  • 25.07.28 학습개발일지 / Makefile+
m_Dev
m_Dev
  • m_Dev
    m_Dev
    m_Dev
  • 전체
    오늘
    어제
    • 분류 전체보기
      • MAIN STUDY
        • 정보보안
        • 빅데이터
        • 정보처리
        • 컴퓨터 구조
        • 기타
      • JOB
        • Study
        • Project
      • LMS 7
        • 개발일지
      • FRAMEWORK
        • Qt
        • MFC
        • Winform
        • WPF
        • MAUI
      • NETWORK
        • Study
        • Assignment
      • PYTHON
        • Set
        • Study
        • Assignment
        • Project
      • C
        • Set
        • Study
        • Assignment
        • Project
      • C++
        • Set
        • Study
        • Assignment
        • Project
      • C#
        • Set
        • Study
        • Assignment
        • Project
      • DATABASE
        • MySQL
        • SQLite
      • IDE
        • VisualStudioCode
        • VisualStudio
        • Pycharm
        • Colab
      • 기타
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
m_Dev
25.07.30 개발학습일지 / C++ Study4(chapter 5, chapter 6)
상단으로

티스토리툴바