1. 개요
어느덧 C++ 클래스 설계 문법을 펌웨어 실무 (디바이스 라이브러리)에 적용하면서 익숙해져 가고 있다.
최근 BSP 라이브러리와 링킹하여 사용하다가 클래스 상속과 관련된 부분에서 문제가 발생하였는데, 클래스 상속에 대한 개념을 다시한번 정리해보고자 하였다.
2. 클래스 접근 제어자 (Access Specifiers) 복습
C++에서는 다음과 같은 세 가지의 접근 제어 지시자를 제공한다.
1. public
2. private
3. protected
(1) public
class MyClass {
public:
int publicVar;
void publicMethod() {
cout << "Public method" << endl;
}
};
int main() {
MyClass obj;
obj.publicVar = 10; // 외부에서 접근 가능
obj.publicMethod(); // 외부에서 접근 가능
}
- public으로 선언된 멤버는 어디에서나 접근 가능. 즉, 클래스 외부에서도 객체를 통해 직접 접근할 수 있다.
(2) private
class MyClass {
private:
int privateVar;
public:
MyClass() : privateVar(0) {}
void setPrivateVar(int value) {
privateVar = value; // private 멤버는 클래스 내부에서만 접근 가능
}
int getPrivateVar() {
return privateVar; // 접근을 위한 퍼블릭 메서드 제공
}
};
int main() {
MyClass obj;
obj.setPrivateVar(10); // 퍼블릭 메서드를 통해 private 멤버에 접근
cout << obj.getPrivateVar(); // 퍼블릭 메서드를 통해 값을 반환
}
- private로 선언된 멤버는 해당 클래스 내에서만 접근 가능. 외부나 파생 클래스에서 접근할 수 없다.
- private 멤버는 클래스 외부에서 접근하려면 퍼블릭 메서드나 퍼블릭 인터페이스를 통해 접근해야 한다.
(3) protected
class BaseClass {
protected:
int protectedVar;
public:
BaseClass() : protectedVar(0) {}
};
class DerivedClass : public BaseClass {
public:
void accessProtectedVar() {
protectedVar = 10; // 기초 클래스 내부에서는 접근 가능
}
};
int main() {
DerivedClass obj;
obj.accessProtectedVar(); // 기초 클래스 내부 메서드를 통해 접근 가능
}
-
- protected로 선언된 멤버는 해당 클래스와 그 클래스를 상속받은 파생(기초) 클래스에서만 접근 가능.
- 클래스 외부에서는 접근할 수 없다.
3. 상속 개념 다이어그램 (자세한 개념은 생략)
4. 오픈소스 C++ 라이브러리를 해석
https://github.com/emelianov/modbus-esp8266
해당 라이브러리는 ESP기반 MCU에서 적용가능한 오픈소스 C++ 라이브러리이다.
Modbus 프로토콜을 쉽게 구현하기 좋게 설계되어 있다. (RS485와 TCP 네트워킹이 구현되어 있어 편리하다)
(1) ModbusRTUTemplate 라는 클래스가 Public 으로 Modbus 클래스를 상속받았다.
(2) ModbusRTUTemplate 라는 클래스는 protected 지시자로 클래스에 사용되는 변수들을 선언하였다.
(3) ModbusRTUTemplate 클래스를 상속하지 않고 사용
(4) ModbusRTUTemplate 클래스를 상속하고 사용
상속의 유형 복습하기
- public 상속
class Base {
public:
int publicVar;
protected:
int protectedVar;
private:
int privateVar;
};
class Derived : public Base {
public:
void show() {
cout << publicVar << endl; // public 멤버에 접근 가능
cout << protectedVar << endl; // protected 멤버에 접근 가능
// cout << privateVar << endl; // private 멤버는 접근 불가
}
};
- protected 상속
class Base {
public:
int publicVar;
protected:
int protectedVar;
private:
int privateVar;
};
class Derived : protected Base {
public:
void show() {
cout << publicVar << endl; // 자식 클래스에서 접근 가능 (protected로 상속됨)
cout << protectedVar << endl; // 자식 클래스에서 접근 가능
// cout << privateVar << endl; // private 멤버는 여전히 접근 불가
}
};
int main() {
Derived d;
// d.publicVar; // 외부에서는 접근 불가
}
- private 상속
class Base {
public:
int publicVar;
protected:
int protectedVar;
private:
int privateVar;
};
class Derived : private Base {
public:
void show() {
cout << publicVar << endl; // 자식 클래스에서 접근 가능 (private로 상속됨)
cout << protectedVar << endl; // 자식 클래스에서 접근 가능 (private로 상속됨)
// cout << privateVar << endl; // 여전히 접근 불가
}
};
int main() {
Derived d;
// d.publicVar; // 외부에서는 접근 불가
}
5. 오버라이딩 개념 (상속관계에 놓인 동일한 멤버?)
- 상속 관계에 놓인 클래스들에서 동일한 이름과 시그니처를 가진 멤버 함수가 있을 때 발생하는 개념.
- 오버라이딩은 부모 클래스의 멤버 함수를 자식 클래스에서 재정의하는 것을 말한다.
- 자식(파생) 클래스가 부모(기초) 클래스의 동작을 자신의 방식으로 변경할 수 있다.
- 오버라이딩의 조건
- 함수의 이름이 부모 클래스와 자식 클래스에서 동일해야 한다.
- 매개변수 (시그니처) 타입이 동일해야 한다.
- 반환 타입도 동일해야 합니다.
- 부모 클래스의 함수가 virtual 함수여야 한다. (C++에서는 virtual 키워드를 통해 오버라이딩을 지원)
#include <iostream>
using namespace std;
class Parent {
public:
virtual void show() { // 부모 클래스의 가상 함수
cout << "Parent's show()" << endl;
}
};
class Child : public Parent {
public:
void show() override { // 자식 클래스에서 오버라이딩
cout << "Child's show()" << endl;
}
};
int main() {
Parent* p = new Child();
p->show(); // Child의 show()가 호출됨
delete p;
}
'Embedded System > 소프트웨어 (C,C++)' 카테고리의 다른 글
FreeRTOS 사용하기 (2) | 2024.10.16 |
---|---|
실시간 운영체제 (RTOS) (1) | 2024.09.04 |
[모듈 제작] 전류 CT 센서 인터페이스 모듈 - RMS 취득 펌웨어 (0) | 2024.08.21 |
[GUI & 터치스크린] LVGL 구현 관련 정리 (0) | 2024.07.31 |
[C/C++] LVGL GUI 라이브러리 (0) | 2024.07.10 |