생성자

sz L·2023년 3월 24일
0

C++

목록 보기
12/40
post-thumbnail

생성자

클래스의 모든 멤버 변수가 모두 public인 경우 초기화 목록(initialization list) 또는 유니폼 초기화(uniform initialization)를 사용해서 초기화를 직접 초기화할 수 있다.

  • 클래스의 이름과 함수의 이름이 동일하다
  • 반환형이 선언되어 있지 않으며, 실제로 반환하지 않는다
  • 생성자도 함수의 일종이니 오버로딩이 가능하다
  • 생성자도 함수의 일종이니 매개변수에 '디폴트 값'을 설정할 수 있다
  • 객체 생성시 딱 한번 호출된다
  • 매개변수가 선언되지 않을 때(인수가 없을 때) 소괄호는 못 쓴다
    • simpleclass sc(); [X]
    • simpleclass sc; [O]
    • simpleclass * ptr = new simpleclass; [O]
    • simpleclass * ptr = new simpleclass(); [O]
#include <iostream>
using namespace std;

class FruitSeller
{
private:
	int APPLE_PRICE;
	int numOfApples;
	int myMoney;
public:
	FruitSeller(int price, int num, int money)
	{
		APPLE_PRICE = price;
		numOfApples = num;
		myMoney = money;
	}
	int SaleApples(int money)
	{
		int num = money / APPLE_PRICE;
		numOfApples -= num;
		myMoney += money;
		return num;
	}
	void ShowSaleResult() const
	{
		cout << "남은 사과: " << numOfApples << endl;
		cout << "판매 수익: " << myMoney << endl;
	}
};

class FruitBuyer
{
private:
	int myMoney;
	int numOfApples;
public:
	FruitBuyer(int money)
	{
		myMoney = money;
		numOfApples = 0;
	}
	void BuyApples(FruitSeller& seller, int money)
	{
		numOfApples += seller.SaleApples(money);
		myMoney -= money;
	}
	void ShowBuyResult() const
	{
		cout << "현재 잔액: " << myMoney << endl;
		cout << "사과 개수: " << numOfApples << endl;
	}
};

int main()
{
	FruitSeller seller(1000, 20, 0);
	FruitBuyer buyer(5000);
	buyer.BuyApples(seller, 2000);

	cout << "과일 판매자의 현황" << endl;
	seller.ShowSaleResult();
	cout << "과일 구매자의 현황" << endl;
	buyer.ShowBuyResult();

	return 0;
}


클래스 외부에 생성자 만들기

#include <iostream>
using namespace std;
#pragma warning(disable:4996)

class Myclass
{
private:
	int age;
	char id;
	char name[10];

	//멤버함수(=메소드): 기능
public:
	Myclass(char* mname);
	Myclass(int mage, char* mname);
	Myclass(int mage, char mid, char* mname); // 생성자 원형
	void getData(); // 메소드 원형(선언)
};

Myclass::Myclass(char* mname) // 생성자 정의
{
	age = 20;
	id = 'M';
	strcpy(name, mname);
}

Myclass::Myclass(int mage, char* mname)
{
	age = mage;
	id = 'M';
	strcpy(name, mname);
}

Myclass::Myclass(int mage, char mid, char* mname)
{
	age = mage;
	id = mid;
	strcpy(name, mname);
}

void Myclass::getData() // 메소드 정의
{
	cout << id << " " << name << " " << age << endl;
}

int main()
{
	Myclass sc1(25, 'W', "sujin");
	sc1.getData();
	Myclass sc2(27, "gyusu");
	sc2.getData();
	Myclass sc3("hyuk");
	sc3.getData();

	return 0;
}


이니셜라이저

생성자를 통해 멤버변수를 초기화하는 것은 불편하기 때문에 C++은 멤버 이니셜라이저를 지원한다
멤버는 클래스 내의 멤버 변수 혹은 멤버 함수를 뜻하고
이니셜라이저는 초기화라는 뜻이다

#include <iostream>
using namespace std;
#pragma warning(disable:4996)

class Myclass
{
private:
	int age;
	char id;
	char name[10];

	//멤버함수(=메소드): 기능
public:
	Myclass(int mage, char mid, char* mname); // 생성자 원형
	void getData(); // 메소드 원형(선언)
};

Myclass::Myclass(int mage, char mid, char* mname) :age(mage), id(mid) // 생성자 정의, 멤버 이니셜라이저를 이용한 멤버 초기화
{
	strcpy(name, mname);
}

void Myclass::getData() // 메소드 정의
{
	cout << id << " " << name << " " << age << endl;
}

int main()
{
	Myclass sc1(25, 'W', "sujin");
	sc1.getData();

	return 0;
}

멤버 이니셜라이저를 사용하면 초기화의 대상을 명확히 인식이 가능하고, 선언과 동시에 초기화가 이뤄지는 바이너리 코드가 생성되기에 성능에도 이점이 있다.

  • 컴파일단에서 선언과 동시에 초기화가 이뤄지기 때문에 const변수도 할당할 수 있다
    객체 생성 시에 초기화를 해주면 된다
  • 메모리 공간의 할당 이후에 생성자의 호출까지 되어야 객체라고 하는데 따라서 반드시 하나의 생성자가 호출되어야 한다
    • 이러한 기준에 예외를 두지 않기 위해 컴파일러는 디폴트 생성자라는 것을 자동으로 삽입해준다

이니셜라이저 사용해서 초기화 시켜야하는 경우

1. 상수(const)멤버 변수
2. 객체멤버 변수
3. 참조멤버 변수
4. 멤버 변수
#include <iostream>
using namespace std;

class ConstSome
{
public:
	const int val; // 상수멤버 변수
	ConstSome(int n) : val(n) {	}

	void printval() {
		cout << val << endl;
	}
};

class RefSome
{
public:
	int& ref; // 참조자 (&), 참조멤버 변수
	RefSome(int n): ref(n) { }
	void printval() {
		cout << ref << endl;
	}
};

class Position
{
public:
	int x, y;
	Position(int ax, int ay) {
		x = ax;
		y = ay;
	}
};

class ObjSome
{
public:
	Position pos;	// 객체멤버 변수
	ObjSome(int ax,int ay): pos(ax,ay) { }
	void printval() {
		cout << pos.x << " " << pos.y << endl;
	}
};

int main()
{
	ConstSome c(10);
	c.printval();

	int n = 20;
	RefSome r(n);
	r.printval();

	ObjSome o(30, 40);
	o.printval();

	return 0;
}


멤버변수로 참조자 선언_feat.이니셜라이저

#include <iostream>
using namespace std;

class AAA
{
public:
	AAA()
	{
		cout << "empty object" << endl;
	}
	void ShowYourName()
	{
		cout << "I'am class AAA" << endl;
	}
};

class BBB
{
private:
	AAA& ref;
	const int& num;

public:
	BBB(AAA &r,const int &n) : ref(r),num(n) { }
	void ShowYourName()
	{
		ref.ShowYourName();
		cout << "and" << endl;
		cout << "I ref num " << num << endl;
	}
};

int main()
{
	AAA obj1;
	BBB obj2(obj1, 20);
	obj2.ShowYourName();

	return 0;
}


private 생성자

객체의 생성이 클래스 외부에서 진행되기 때문에 생성자는 public으로 선언되어야 한다.

! 클래스 내부에서 객체를 생성한다면, 생성자가 private으로 선언되어도 된다.
  • 클래스 내부에서만 객체의 생성을 허용하려는 목적으로 생성자를 private로 선언하는 예제
#include <iostream>
using namespace std;

class AAA
{
private:
	int num;
public:
	AAA() : num(0) { }
	AAA& CreareInitObj(int n) const
	{
		AAA* ptr = new AAA(n);
		return *ptr;
	}
	void ShowNum() const { cout << num << endl; }
private:
	AAA(int n) : num(n) {} //private로 선언된 생성자
};

int main()
{
	AAA base;
	base.ShowNum();

	AAA& obj1 = base.CreareInitObj(3);
	obj1.ShowNum();

	AAA& obj2 = base.CreareInitObj(12);
	obj2.ShowNum();

	delete& obj1;
	delete& obj2;

	return 0;
}

profile
가랑비는 맞는다 하지만 폭풍은 내 것이야

0개의 댓글