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 멤버 접근 가능
- Static 멤버가 public으로 선언된 경우
예제 코드 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++의 연산자 중복 대상
- 객체 가능
- 문자열 가능
- 추가적인 연산자 중복 정의 가능
중복 가능 연산자의 종류
| + | - | * | / | % | ^ | & |
| | | ~ | ! | = | < | > | += |
| -= | *= | /= | %= | ^- | &= | |= |
| « | » | »= | «= | == | != | >= |
| <= | && | || | ++ | – | ->* | . |
| -> | [] | () | new | delete | new[] | 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}
//정렬된 두 배열을 결합한 새로운 배열 탄생
구현 방법
- 클래스의 멤버 함수로 구현하는 방법
- 외부 함수로 구현하고 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 라이센스를 따릅니다.