클래스 응용 2

킴스코딩클럽·2022년 11월 25일
1

class 이름
{
private:
	//멤버 목록

public:
	//멤버목록
}

생성자 : 생성자 초기화 리스트
소멸자

const class

class MyClass
{
public:
    int m;
    int m2;

    MyClass(): MyClass(1, 1)
    {
        //초기화됨
    }
    MyClass(int m, int m2): m{m}, m2{m2}
    {
        //대리생성자로 멤버들이 초기화됨
    }

    void Setm(int x)
    {
        m = x;
    }

    void Print()
    {
        std::cout << m << "," << m2 << std::endl;
    }
};

int main() {
    const int x = 1;

    //기본 생성자로 초기화된 상수 인스턴스
    const MyClass c1;
    const MyClass c2(2, 2); 
    //대리생성자로 멤버 변수로 초기화되서 c2라는 상수 인스턴스가 만들어짐

    // c1.m = 3; 불가능 상수라서
    /*c1.Setm(3); 
    this에 &c1이 들어오는데 c1은 const객체->
    그러면 const객체의 멤버는 변경할 수 없음
    상수객체는 사용 불가능함
    c1.Print();
    이미 this에 &c1 상수 객체가 넘어간 것 -> 
    상수 객체가 넘어간다는 것은 값을 바꾸는 것이 아니라 사용만 하더라도 위험요소가 존재함
    문법적인 위험 요소가 남게 됨 (상수라는 표기에 올바르지 않음-> 초기화되면 바꿀 수 없다는 전재조건)
    */

}

멤버 함수를 못 쓰나요? 
- 오직 하나 : 상수 멤버 함수
- 멤버 함수가 인스턴스를 바꾸지 않는다는 것

static Instace

class<클래스명>
{
	...
    static<타입><변수명>;
};

<타입><클래스명>::<변수명>;
class MyClass 
{
	//클래스 선언 -> 타입 선언과 같음
	//실체가 없음(인스턴스가 만들어지기 전까지는) 개념적인 것
public:
	static int mValue;
	//정적 멤버변수 : 멤버변수가 인스턴스에 종속되지 않는 클래스 변수
};

int MyClass::mValue;
//선언이 위에 있기 때문에 정의가 필요함

int main() 
{
	MyClass c1;

	//c1.mValue = 1; 
	//c1이라는 인스턴스의 멤버이기 때문에 이런 방식은 사용 불가
	//인스턴스를 찍어내는 클래스에 속해야함

	MyClass::mValue = 1;
	std::cout << MyClass::mValue << std::endl;
}

클래스 활용 방법

int main() 
{
	{
		MyClass c1, c2, c3;
		//3번의 생성자가 불림 -> this->가 아니라 myclass::라서 한 번 만들고 나면 유지됨
		//그래서 갯수가 3이 나옴

		std::cout << MyClass::mValue << std::endl;
	}
	std::cout << MyClass::mValue << std::endl;
	//0이 나옴
	//이런 개념을 이용해서 함수가 몇번 불리는지 확인해서 최적화에 사용함
}

static member function

  • 암시적 객체 this가 없음
class OrderTicket 
{
private:
	static int mID;

public:
	void Normal() {
		this->mID;

	}

	static int Publish() //static 멤버 함수
	{
		return ++mID;
		//this->mID가 아니고 OrderTicket::mID
		//스테틱 함수에서는 this 못 씀
	}
	//리소스를 관리하는 용도로 manager개념 사용
};

int OrderTicket::mID {};

int main() 
{
	OrderTicket C1;

	/*std::cout << C1.Publish() << std::endl;
	std::cout << C1.Publish() << std::endl;
	std::cout << C1.Publish() << std::endl;*/

	std::cout << OrderTicket::Publish() << std::endl;
	std::cout << OrderTicket::Publish() << std::endl;
	std::cout << OrderTicket::Publish() << std::endl;
}

friend

  • 친구는 private (protected)멤버 접근이 가능
  • A가 B를 친구라고 지정하면 B는 A의 모든 것을 알 수 있음
  • 일방적인 관계라서, B는 A의 친구가 아님
  • 친구의 친구는 친구가 아님
  • C++만 있는 기능
  • 연산자 오버로딩(operator overloading)에서 유용하게 사용
  • 캡슐화(숨기고 못 쓰게 하는) 기능에 반대되는 기능 -> 예외라서 문제가 생길 수 있음
//friend class
class Sword
{
	friend class Warrior;

private:
	int damage;

public:
	Sword(int dmg): damage {dmg} 
	{

	}
};

class Warrior
{
public:
	void AttackWith(Sword &s) {
		std::cout << "칼로" << s.damage << "피해줌" << std::endl;
		//소드가 워리어를 친구로 지정해야함 
		//숨기는 사람이 공개 여부를 지정해야함
	}
};

int main() {
	Sword knife {10};
	Warrior w;

	w.AttackWith(knife)

	knife. //친구에게만 공개됨 ->warrior 클래스 에게만 공개되는 것
}
  • 친구 함수
  • 친구 멤버 함수
class Sword; //이름만 알려줌

class Warrior
{
public:
	void AttackWith(Sword &s);
	//정의를 sword뒤로 보냄 ->

};

//friend class
class Sword
{
	//friend class Warrior;

	friend void Warrior::AttackWith(Sword &sword);
	//친구 멤버 함수 : Sword가 선언될 때 warrior가 뭔지 모르기 때문에 컴파일 에러
	//함수의 전방 선언처럼 미리 선언하기 


	//멤버 함수가 아니고 전역 함수 Sword 클래스와는 아무 상관없음
	friend void Upgrade(Sword &sword)
	{
		int old = sword.damage;

		sword.damage = old * 2;
		//어쩔 수없이 멤버에 접근해야함 -> 이 함수를 친구로 지정함


	}

private:
	int damage;

public:
	Sword(int dmg): damage {dmg} 
	{

	}
};



int main() {
	Sword knife {10};
	Warrior w;

	w.AttackWith(knife);

	//knife.  
	//친구에게만 공개됨 ->warrior 클래스 에게만 공개되는 것

	Upgrade(knife);
	w.AttackWith(knife);
}

void Warrior::AttackWith(Sword &s)
{
	std::cout << "칼로" << s.damage << "피해줌" << std::endl;
	//소드가 워리어를 친구로 지정해야함 
	//숨기는 사람이 공개 여부를 지정해야함
}

연산자 오버로딩(operator overloading)

  • operator : operand들을 연산 후 값 반환 -> 함수처럼 작동한다
class Point2D
{
private:
	int my;
	int mx;

public:
	Point2D():Point2D(0, 0){}
	Point2D(int x, int y):mx(x), my(y)
	{

	}

	void Print()
	{
		std::cout << "(" << mx << "," << my << ")" << std::endl;
	}
	friend Point2D operator+(const Point2D& operand1, const Point2D& operand2);
};

Point2D operator+(const Point2D& operand1, const Point2D& operand2)
{
	Point2D result;

	result.mx = operand1.mx + operand2.mx;
	result.my = operand1.my + operand2.my;
	//친구함수로 프라이빗 멤버에 접근

	return result;
}

int main() {
	Point2D pt1(2, 3), pt2(3, 4);

	pt1.Print();
	pt2.Print();

	Point2D pt3;
	
	///이 기능이 연산자 오버로딩
	pt3 = pt1 + pt2;
	
	//pt3 = operator+(pt1, pt2);
	
	pt3.Print();

	Point2D pt4;

	pt4 = (pt1 + pt2) + pt3;//참조형 - rvalue라서 에러가남 ->  const를 붙여서 해결(const 참조형) -> const는 정해진 것은 아님 rvalue를 사용할 때만 사용
}

anonymous object(무명객체)

///r-value : anonymous object (무명객체, 익명객체)


class MyClass
{
public:
	int value;
	
	MyClass(int v): value {v}
	{
		std::cout << "[construct]:" << value << std::endl;
	}

private:

};

MyClass operator*(MyClass op1, MyClass op2) {
	///MyClass result(0);//객체 생성
	///result.value = op1.value * op2.value;
	/// 
	///return result;
	return MyClass(op1.value + op2.value);
	//연산자의 결과로 객체가 생성될 수 있음
	//이게 무명객체
}
MyClass Square(MyClass x)
{
	return x * x;
}


int plus(int x)
{
	//int temp = x + x;
	//return temp;
	//rvalue :이름이 없는 객체
	
}


int main()
{
	MyClass x {2}, y {0};
	y = Square(x);

	std::cout << y.value << std::endl;
	//객체가 총 3번 생성됨 ->> 2 , 0 , 0 >> 4
}
profile
공부 기록용

0개의 댓글