1
클래스와 구조체의 근본적인 차이가 무엇일까.
은닉 기능의 차이다.
C++의 접근제한자 3가지 private, protected, public이 있다.
private로 선언하면 클래스 내부의 멤버 함수 또는 friend 함수만 클래스의 private 멤버에 접근할 수 있다.
protected로 선언하면 클래스 외부에서는 protected 멤버에 접근할 수 없다.
해당 클래스의 하위 클래스(상속)에서는 접근할 수 있다.
public으로 선언된 데이터 멤버와 메서드는 다른 클래스에서도 접근이 가능하다.
public 멤버는 . 연산자를 사용하여 접근한다.
2
friend 키워드를 통해 특정한 객체의 모든 멤버에 접근할 수 있다.
friend를 통해서 함수를 작성하면 그 함수는 클래스의 메서드로 인식되지 않는다. 그렇지만 private 멤버에 접근할 수 있게된다.
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
int studentId;
string name;
public:
Student(int studentId, string name): studentId(studentId), name(name) { }
// friend 키워드를 이용해 다른 객체의 private 멤버인 name에 바로 접근 가능.
friend Student operator +(const Student &student, const Student &other) {
return Student(student.studentId, student.name + " & " + other.name);
}
// 아래와 같이 대체할 수 있다.
// Student operator +(const Student &other) {
// return Student(studentId, name + " & " + other.name);
// }
void showName() { cout << "name: " << name << '\n'; }
};
int main(void) {
Student student(1, "Alex");
Student result = student + student;
result.showName();
}
// output
// Name: Alex & Alex
friend 키워드를 굳이 써야할까?
Student operator +(const Student &student, const Student &other) {
return Student(student.studentId, student.name + " & " + other.name);
}
// error: ‘Student Student::operator+(const Student&, const Student&)’ must have either zero or one argument
operator 함수는 0 혹은 1개의 인자까지만 받을 수 있다.
3
아래와 같이 클래스 밖에 함수를 정의하여 가독성을 높일 수 있다.
#include <iostream>
#include <string>
using namespace std;
class Friend1 {
private :
string name;
//이렇게 자신의 private 멤버에 참조가 가능한 함수가 있다고 선언해주어야한다.
friend void set_name(Friend1&, string);
};
// 클래스 밖에서 함수 정의
void set_name(Friend1& f, string s) {
f.name = s;
cout << f.name << "\n";
}
int main(void) {
Friend1 f1;
set_name(f1, "Alex");
return 0;
}
4
friend 키워드를 클래스에 쓰면 이렇게 된다.
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
class Time {
friend class Date; // Date 클래스에서 Time 클래스를 이용할 수 있음.
private:
int hour, min, sec;
public:
void setCurrentTime() {
time_t currentTime = time(NULL);
struct tm *p = localtime(¤tTime);
hour = p->tm_hour;
min = p->tm_min;
sec = p->tm_sec;
}
};
class Date {
private:
int year, month, day;
public:
Date(int year, int month, int day): year(year), month(month), day(day) { }
void show(const Time &t) {
cout << "지정된 날짜: " << year << "년 " << month << "월 " << day << "일" << '\n';
cout << "현재 시간: " << t.hour << ":" << t.min << ":" << t.sec << '\n';
}
};
int main(void) {
Time time;
time.setCurrentTime();
Date date = Date(2021, 05, 13);
date.show(time);
}
friend가 안되어있으면 Time클래스의 메서드로 Time클래스의 private영역에 들어가야하지만, friend class로 지정해주면서 Date클래스에서 직접 private 속성에 들어가게 해준다.
5
정적 멤버(Static Member)란 클래스에는 포함 되어 있는 멤버이지만 모든 객체가 공유하는 멤버. 그러므로 메모리 상에 오직 하나만 할당되어서 관리된다.
정적 멤버를 public으로 선언하면 모든 외부 클래스/함수에서 접근하여, 오직 하나의 멤버변수를 관리할 수 있다.
#include <iostream>
#include <string>
using namespace std;
class Person {
private:
string name;
public:
static int count;
//객체가 하나 생길떄마다,(생성자가 사용될때마다.) count가 1 올라간다.
Person(string name) : name(name) {
count++;
}
};
//여기에 Person class의 count를 선언하면 Person class의 모든 객체에서 참조가 가능해진다.
int Person::count = 0;
int main(void) {
Person p1("Alex");
Person p2("Bob");
Person p3("Cert");
cout << "사람의 수: " << Person::count << '\n';
}
// output
// 사람의 수: 3
참고
임시객체와 const사용에 관한 글
https://supark7.tistory.com/entry/19-%EC%9E%84%EC%8B%9C%EA%B0%9D%EC%B2%B4
const와 pointer
https://dydtjr1128.github.io/cpp/2020/01/08/Cpp-const.html
연산자 오버로딩과 friend 키워드
https://choryeonworkshop.tistory.com/130
https://thrillfighter.tistory.com/283
static 키워드