" /> C++ 9주차 프렌드와 연산자 중복 | BlackWerf's Blog
포스트

C++ 9주차 프렌드와 연산자 중복

함수 중복 간소화

디폴트 매개변수 이용한 함수 중복 간소화

예시 코드

1
2
3
4
5
6
Circle() { radius = 1; }
Circle(int r) { radius = r; }

			||

Circle(int r=1) { radius = r; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void drawSymbol(){
	for(int i=0; i<10; i++) cout << '*';
	cout << endl;
}
void drawSymbol(int n, char c){
	for(int i=0; i<n; i++) cout << c;
	cout << endl;
}


				||
			
void drawSymbol(int n=10; char c='*'){
	for(int i=0; i<n; i++) cout << c;
	cout << endl;
}
  • 디폴트 매개 변수는 함수 중복의 함수 구분과 관계 X


함수 중복의 모호성

정상 컴파일

double square(double a) { return a*a; }

int main() { cout << square(3); }

변수의 형 변환으로 인한 함수 중복의 모호성

1
2
3
4
float square(float a) {return a*a;}
double square(double a) { return a*a; }

int main() { return square(3) }

디폴트 매개 변수로 인한 함수 중복의 모호성

1
2
3
4
 void msg(int id) { cout << id << endl;  }
 void msg(int id, string s= "") { cout << id << ":" << s << endl; }

 int main() { msg(5); }

참조 매개 변수로 인한 함수 중복의 모호성

1
2
3
4
5
6
7
int add(int a, int b)    { return a + b; }
int add(int a, int &b) { return b = b + a; }

int main(){
	int a=10, b=20;
	cout << add(a,b,);
}


Static

정의

  • 변수의 선언
  • 프로그램 시작 시점에서 생성 및 종료할때 소멸

  • 클래스의 Static 멤버
    • Static 멤버 * 프로그램 시작시 생성 * 클래스 당 하나만 생성(모든 객체가 하나의 멤버를 공유)
    • 선언
      • static 변수타입 변수명;
      • Ex) static int totalAccount;
    • 초기화 * static 멤버 변수에 대한 클래스 외부 초기화가 필요 * Ex) int Bank::totalAccount = 0;


예제 코드

class Bank { public : static int totalAccount; };
int Bank::toatalAccount = 0;


예제 코드 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

using namespace std;
class Person {
		
		  public:
			  int money; //개인 소유의 돈
			  int id;
			  int myAccount;

			  void addMoney(int money) { this->money += money; }
			  static int sharedMoney; //공금
			  static void addShared(int n) { sharedMoney += n; }
};
int Person::sharedMoney = 10; //10으로 초기화
int main() {
	Person kim;
	kim.money = 100; //Kim의 개인돈 = 100
	kim.sharedMoney = 200; //공금이라는 static 변수에 접근해 200으로 설정

	Person lee;
	lee.money = 150; //lee의 개인돈  = 150
	lee.addMoney(200);
	lee.addShared(200);

	cout << kim.money << ' ' << lee.money << endl;
	cout << kim.sharedMoney << ' ' << lee.sharedMoney << endl;
}

Output

1
2
100 350
400 400

예제 코드 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Person2 {

public:
	int money; //개인 소유의 돈
	int id;
	int myAccount;

	void addMoney(int money) { this->money += money; }
	static int sharedMoney; //공금
	static void addShared(int n) { sharedMoney += n;}
};
int Person2::sharedMoney = 10; //10으로 초기화

int main(){
Person2::addShared(50); //공금에 접근해 60으로 설정
cout << Person2::sharedMoney << endl;
Person2 kim;
kim.money = 100;
kim.sharedMoney = 200; //공금 : 200

Person2::sharedMoney = 300; //공금 : 300
Person2::addShared(100); // 공금 ㅣ 400
cout << kim.money << ' ' << Person2::sharedMoney << endl;
}

Output

1
2
60
100 400


범위 지정 연산자(::)를 이용한 Static 멤버 접근

  • Static 멤버는 클래스에 하나만 생성되므로, 클래스 이름, 범위 지정 연산자를 이용해 접근이 가능함

  • 형식

    클래스명:: static멤버

    1
    2
    3
    4
    5
    6
    7
    
    kim.sharedMoney = 200;
    lee.addShared(200);
      
    		||
      
    Person::sharedMoney = 200;
    Person::addShared(200);
    

Static의 활용

  • 객체 사이에 공유
    • Static 멤버 선언한 클래스로부터 생성된 모든 객체들을 공유
  • 제약사항
    • Static 멤버가 public으로 선언된 경우
      • 클래스의 캡슐화 유지 불가
      • 외부에서 static으로 선언된 멤버 접근 가능
    • Static 멤버 함수의 접근
      • static 멤버 함수는 non-static 멤버 접근 불가
      • non-static 함수는 static 멤버 접근 가능

예제 코드 3

1
2
3
4
5
6
7
8
9
10
11
12
class Math {
	public:
		static int abs(int a) { return a > 0 ? a : -a; }
		static int max(int a, int b) { return a > b ? a : b; }
		static int min(int a, int b) { return a > b ? b : a; }
};

int main(){
	cout << Math::abs(-1) << endl;
	cout << Math::max(10, 20) << endl;
	cout << Math::min(-5, 5) << endl;
}

Output

1
2
3
1
20
-5


예제 코드 4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Circle {
private:
	static int numOfCircles;
	int radius;
public:
	Circle(int r = 1);
	~Circle() { numOfCircles--; } //생성된 원의 개수 감소
	static int getNumOfCircles() { return numOfCircles; }
};
Circle::Circle(int r) {
	radius = r;
	numOfCircles++;
}
int Circle::numOfCircles = 0;  //0으로 초기화

int main(){
	Circle* p = new Circle[10]; //10개 생성자 실행
	cout << "생성된 원의 개수 = " << Circle::getNumOfCircles() << endl;
	delete[] p; //10개의 소멸자 실행
	cout << "생성된 원의 개수 = " << Circle::getNumOfCircles() << endl;
	Circle a; //생성자 실행
	cout << "생성된 원의 개수 = " << Circle::getNumOfCircles() << endl;
	Circle b; //생성자 실행
	cout << "생성된 원의 개수 = " << Circle::getNumOfCircles() << endl;
}

Output

1
2
3
4
생성된 원의 개수 = 10
생성된 원의 개수 = 0
생성된 원의 개수 = 1
생성된 원의 개수 = 2


Friend

프랜드 함수

  • 클래스의 멤버가 아닌 외부 함수
  • 클래스의 모든 멤버를 접근 할 수 있는 권한 보유
  • 종류
    • 전역 함수 : 클래스 외부에 선언된 전역 함수
    • 다른 클래스의 멤버 함수
    • 다른 클래스의 모든 멤버 함수


예제 코드 5 - 외부 전역 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Rectangle;
bool equals(Rectangle r, Rectangle s);
class Rectangle {
	int width, height;
public:
	Rectangle(int width, int height) { this->width = width; this->height = height; }
	friend bool equals(Rectangle r, Rectangle s);
};
bool equals(Rectangle r, Rectangle s) {
	if (r.width == s.width && r.height == s.height)
		return true;
	else
		return false;
}

int main(){
	Rectangle a(1, 2), b(3, 4);
	if (equals(a, b))
		cout << "equal" << endl;
	else
		cout << "not equal" << endl;
}

Output

1
not equal

예제 코드 6 - 다른 클래스의 멤버 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Rectangle2;
class Rectangle2Manager {
	public:
		bool equals(Rectangle2 r, Rectangle2 s);
};
class Rectangle2 {
	int width, height;
	public:
		Rectangle2(int width, int height) { this->width = width; this->height = height; }
		friend bool Rectangle2Manager::equals(Rectangle2 r, Rectangle2 s);
};
bool Rectangle2Manager::equals(Rectangle2 r, Rectangle2 s) {
	if (r.width == s.width && r.height == s.height) return true;
	else return false;
}


int main(){
	Rectangle2 a(1, 2), b(3, 4);
	Rectangle2Manager manage;
	if (manage.equals(a, b)) cout << "equal" << endl;
	else cout << "not equal" << endl;
}

Output

1
not equal


예제 코드 7 - 다른 클래스의 모든 멤버 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Rectangle3;
class RectangleManager3 { //RectangleManager 클래스 선언
public:
	bool equals(Rectangle3 r, Rectangle3 s);
	void copy(Rectangle3& dest, Rectangle3& src);
};
class Rectangle3 { //Rectangle 클래스 선언
	int width, height;
public:
	Rectangle3(int width, int height) { this->width = width; this->height = height; }
	friend RectangleManager3;
};
bool RectangleManager3::equals(Rectangle3 r, Rectangle3 s) {
	if (r.width == s.width && r.height == s.height) return true;
	else return false;
};
void RectangleManager3::copy(Rectangle3& dest, Rectangle3& src) { dest.width = src.width; dest.height = src.height; };

int main(){
    Rectangle3 a(3,4), b(5,6);
    RectangleManager3 manage;
    manage.copy(b,a); //b를 a에 복사
    if(manage.equals(a,b)) cout << "equal" << endl;
    else cout << "not equal" << endl;
}

Output

1
equal

연산자 중복

일반적인 연산자의 대상

  • 숫자만 가능
  • 문자열 불가
  • 객체 불가

C++의 연산자 중복 대상

  • 객체 가능
  • 문자열 가능
  • 추가적인 연산자 중복 정의 가능

중복 가능 연산자의 종류

       
+-*/%^&
|~!=<>+=
-=*=/=%=^-&=|=
«»»=«===!=>=
<=&&||++->*.
->[]()newdeletenew[]delete[]

중복 불가능 연산자의 종류

    
..*::?:


더하기

1
2
3
int a = 2, b = 3, c;
c = a + b;
//결과 : 5, 정수가 피연산자일때 2와 3 합치기

문자열 합치기

1
2
3
string a = "C", c;
c = a + "++"; //결과 : "C++"
//문자열이 피연산자일때 두 문자열 합치기

배열 합치기

1
2
3
SortedArray a(2,5,9), b(3,7,10), c;
c = a+ b; // {2,3,5,7,9, 10}
//정렬된 두 배열을 결합한 새로운 배열 탄생

구현 방법

  1. 클래스의 멤버 함수로 구현하는 방법
  2. 외부 함수로 구현하고 friend 함수로 선언

형식:

  • 리턴타입 operator연산자(매개변수 리스트);

  • Ex) friend Circle operator+(Circle c1, Circle c2);

    1
    2
    3
    4
    5
    6
    7
    8
    
    Circle operator + (Circle op1, Circle op2);  //외부 함수
    Circle operator == (Circle op1, Circle op2); //외부 함수
      
    class Circle{
        ...
        friend Circle operator+ (Circle op1, Circle op2);
        friend bool operator== (Circle op1, Circle op2);
    };
    
  • Circle operator+(Circle c);

    1
    2
    3
    4
    5
    
    class Circle{
    	...
        Circle operator+ (Circle op2);
        Circle operator== (Circle op2);
    }
    


이항연산자 + 중복

c = a+b

c = a. + (b);

Circle operator+(Circle c1);

1
2
3
4
5
6
7
class Circle {
    int radius;
    int price;
 public:
    ...
	    Circle operator+(Circle c1);
}

함수의 구현

1
2
3
4
5
6
Circle Circle::operator+(Circle c1){
    Circle tmp;
    tmp.radius = this->radius + c1.radius;
    tmp.price = this->price + c1.price;
    return tmp;
}

함수의 구현 스크립트에서 this는 a. 객체를 의미

**예제 8 **

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Circle8 {
	int radius;
	int price;
	public:
		Circle8(int radius = 0, int price = 0) { this->radius = radius;  this->price = price; }
		void Show();
		Circle8 operator+ (Circle8 op2); //+연산자 함수 선언
};
void Circle8::Show() { cout << "radius=" << radius << "," << "price=" << price << endl; }
Circle8 Circle8::operator+(Circle8 op2) {
	Circle8 tmp; //임시 객체
	tmp.radius = this->radius + op2.radius; //radius 더하기
	tmp.price = this->price + op2.price; //price 더하기
	return tmp;
};


int main(){
    Circle8 a(3, 5), b(4, 6), c;
	c = a + b;
	a.Show();
	b.Show();
	c.Show();
}

Output

1
2
3
radius=3,price=5
radius=4,price=6
radius=7,price=11

== 연산자 중복

  • 매개변수 타입과 관계없는 비교 연산자 중복

    1
    2
    3
    4
    5
    6
    7
    
    class Circle{
        int radius;
        int price;
     public:
        ...
            bool operator==(Circle c1);
    };
    

    함수 구현

    1
    2
    3
    4
    
    bool Circle::operator==(Circle c1){
        if(radisu==c1.radius && price == c1.price) return true;
        else return false;
    }
    

연산자 중복 == 예시

class Circle9 {
	int radius;
	int price;
public:
		Circle9(int radius = 0, int price = 0) { this->radius = radius;  this->price = price; }
		void Show();
		bool operator== (Circle9 op2);
};

void Circle9::Show() { cout << "radius=" << radius << ',' << "price=" << price << endl; };
bool Circle9::operator==(Circle9 op2) {
	if (radius == op2.radius && price == op2.price) return true;
	else return false;
}


int main() {
	//== 연산자 중복
	Circle9 a(3, 5), b(3, 5); //2개 객체 생성
	a.Show();
	b.Show();
	if (a == b) cout << "두 원이 같음" << endl;
	else cout << "두 원이 다름" << endl;
}

Output

1
2
3
radius=3,price=5
radius=3,price=5
두 원이 같음

다른 타입과 + 연산자 중복

  • 예시: a. + (2)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    class Circle10 {
    	int price;
    	int radius;
    public:
    	Circle10(int radius = 0, int price = 0) { this->radius = radius; this->price = price; }
    	void show();
    	Circle10 operator+ (int op2); //+ 연산자 함수 선언
    };
    void Circle10::show() { cout << "radius=" << radius << ',' << "price=" << price << endl; }
    Circle10 Circle10::operator+(int op2) {
    	Circle10 tmp; //임시 객체 생성
    	tmp.radius = radius + op2;
    	tmp.price = radius + op2;
    	return tmp;
    }
      
      
    int main(){
        Circle10 a(3, 5), b;
    	a.show();
    	b.show();
    	b = a + 2;
    	a.show();
    	b.show();
    }
    
    1
    2
    3
    4
    
    radius=3,price=5
    radius=0,price=0
    radius=3,price=5
    radius=5,price=7
    
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.