
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 ©)
: 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 |