나만의 작은 도서관
[C++][Class] 클래스 관련 기타 내용(explicit, mutable, friend 키워드 등...) 본문
C++/문법 및 메소드(STL)
[C++][Class] 클래스 관련 기타 내용(explicit, mutable, friend 키워드 등...)
pledge24 2025. 3. 26. 02:19explicit 키워드
explicit Mystring(int capacity); // 생성자를 explicit으로 지정
- 대입 연산자가 생성자로 암시적 변환되지 못하도록 막는 키워드.
암시적 변환(implicit conversion) 시 문제점
- 암시적 변환은 프로그래머가 명시적으로 변환을 요청하지 않더라도 컴파일러가 자동으로 처리하는 타입 변환을 말한다.
- 이러한 암시적 변환은 아래의 예시에서 대입 연산자가 생성자로 변환되는 것처럼, 원하지 않는 방식으로 변환되는 문제가 있다.
class MyClass {
public:
MyClass(int x) { cout << "MyClass Constructor" << '\\n';}
};
void func(MyClass myclass) { cout << "func" << '\\n';}
// [MyClass myclass = 3] => [MyClass myclass(3)]으로 암시적 변환 발생
func(3); // func(MyClass(3))이 실행.
// 실행 결과
// MyClass Constructor
// func
- 이러한 암시적 변환을 막기 위해 생성자 앞에 explicit을 추가하여 대입 연산자가 생성자로 변환되는 것을 막는다.
- 참고로 explicit으로 지정한 생성자만 암시적 변환이 막히기 때문에, explicit을 선언하지 않은 생성자로는 암시적 변환이 될 수 있다.
=> 암시적 변환을 금지하려면 모든 생성자를 explicit으로 지정해야 한다!
- 참고로 explicit으로 지정한 생성자만 암시적 변환이 막히기 때문에, explicit을 선언하지 않은 생성자로는 암시적 변환이 될 수 있다.
class MyClass {
public:
/* explicit 선언 */
explicit MyClass(int x) { cout << "MyClass Constructor" << '\\n';}
};
// [MyClass myclass = 3] => [MyClass myclass(3)]으로 암시적 변환 금지됨
void func(MyClass myclass) { cout << "func" << '\\n';}
int main(void){
func(3); // 컴파일 오류: "int"에서 "MyClass"(으)로 변환하기 위한 적절한 생성자가 없습니다.
return 0;
}
mutable 키워드
mutable int data_;
- 상수 함수에서 멤버 변수의 값을 수정할 수 있도록 바꿔주는 키워드.
mutable 키워드를 사용하는 이유
- 상수 함수는 “이 함수는 객체의 내부 상태에 영향을 주지 않습니다.”라는 의도를 가지고 있다. 즉, 해당 함수가 읽기 작업만을 수행한다는 의도를 명시할 수 있다.
- 하지만 아주 낮은 빈도로 일부 변수의 값을 변경해야 하는 작업이 있을 수 있는데, 이러한 작업을 수행하기 위해서는 함수를 상수 함수로 지정할 수 없다.
- 참고로 상수 함수에서 호출하는 함수 또한 쓰기 작업을 할 수 없다.(호출 함수가 상수 함수가 아니어도)
- 하지만 mutable 키워드는 사용하면 상수 함수로 유지하면서 mutable로 지정한 멤버 변수에 대해 쓰기 작업을 할 수 있으므로, 위와 같은 문제를 해결할 수 있다.
class Cache {
public:
void UpdateCache(const int data) const {
_data = data; // mutable 이므로 수정 가능!
}
void GetData(const int data) const { // 상수 함수 정의
if(data == _data)
cout << "cache Hit! " << '\\n';
else{
cout << "cache Miss... " << '\\n';
UpdateCache(data); // 데이터 갱신
}
}
private:
mutable int _data = -1; // 초기값 -1
};
int main() {
Cache cache; // 크기가 1인 캐시
cache.GetData(10); // cache Miss...
cache.GetData(10); // cache Hit!
}
friend 키워드
friend class ClassName;
friend void func(int x);
- friend 키워드는 지정한 대상에게 private 또는 protected 멤버 변수와 함수에 접근할 수 있도록 허용하는 키워드이다.
- 지정된 대상은 해당 클래스의 private 멤버 변수에 접근할 수 있지만, 반대로 지정된 대상의 private 멤버 변수는 해당 클래스가 접근할 수 없다.
- A가 B를 friend로 지정 시
- B → A 접근 (O)
- A → B 접근 (X)
- A가 B를 friend로 지정 시
- friend 키워드의 주목적은 일부 대상만 private 멤버 변수에 접근할 수 있도록 하기 위함이다.
#include <iostream>
using namespace std;
class A
{
public:
/* 멤버 "B::privateKey"에 액세스할 수 없습니다. */
// void showOtherKey(const B& other) {cout << other.privateKey << '\\n';}
private:
friend class B;
string privateKey = "A's private Key";
};
class B
{
public:
void showOtherKey(const A& other) {cout << other.privateKey << '\\n';}
private:
string privateKey = "B's private Key";
};
int main(void){
A a;
B b;
b.showOtherKey(a); // 실행 결과: A's private
}
abstract과 sealed 키워드
virtual void func2() abstract;
virtual void func2() sealed;
- abstract과 sealed 키워드는 C++ 표준 키워드가 아닌 Visual Studio (MSVC)에서 확장 기능으로 제공하는 키워드이다.
- abstract 키워드는 C++ 표준의 순수 가상 함수 표현인 ‘ = 0’ 역할을 하며, 클래스 이름 뒤나 함수 이름 뒤에 붙일 수 있다.
- 클래스 이름 뒤에 붙이는 abstract는 추상 클래스임을 알리기 위한 가독성용일 뿐 기능은 없다.
- sealed 키워드는 C++ 표준의 재정의를 금지하는 final 키워드 역할을 한다.
- 결론적으로 abstract, sealed 둘 다 기능적인 면에선 C++ 표준으로 대체가 되는 키워드들이므로, 가독성 면에서만 장점이 있다.
멤버 클래스(Member Class)
- 멤버 클래스는 클래스의 멤버 변수로 존재하는 클래스를 의미한다.
- 멤버 클래스는 포함 관계(has-a)에 해당하는 클래스이다.
class Engine {
public:
Engine() { std::cout << "Engine 생성\\n"; }
};
class Car {
Engine engine; // Engine이 Car의 멤버 클래스
public:
Car() { std::cout << "Car 생성\\n"; }
};
중첩 클래스(Nested Class)
- 중첩 클래스는 어떤 클래스의 내부에 정의된 클래스를 의미한다.
- 중첩 클래스는 외부 클래스와 논리적으로 강한 관계가 있는 클래스를 그룹화하여 코드의 가독성을 높이고, 외부에서 직접적인 접근을 제한하기 위해 사용한다.
- 중첩 클래스를 사용하는 사례로 연결 리스트, 트리 등의 자료 구조가 있다.
#include <iostream>
class Outer {
private:
int outerValue;
public:
Outer(int v) : outerValue(v) {}
// 중첩 클래스 정의
class Inner {
public:
void show() {
std::cout << "Inner class method" << std::endl;
}
};
};
int main() {
// 중첩 클래스 객체 생성
Outer::Inner innerObj;
innerObj.show(); // 출력: Inner class method
return 0;
}
참고 자료
https://stackoverflow.com/questions/1298093/can-i-use-abstract-keyword-in-c-class
'C++ > 문법 및 메소드(STL)' 카테고리의 다른 글
[C++] 전방 선언(Forward Declaration) (0) | 2025.03.28 |
---|---|
[C++] 캐스팅(Casting) (0) | 2025.03.28 |
[C++][Class] 오버라이딩과 가상 함수 (0) | 2025.03.26 |
[C++][Class] 상속(Inheritance) (0) | 2025.03.26 |
[C++][Class] 연산자 오버로딩(Operator Overloading) (0) | 2025.03.25 |