C++ for Pixhawk
C++ 발표 자료(추가)
https://docs.google.com/presentation/d/1utKTH0baDk7a2X9YDm-M3QjpMTWS9nqMAcuXNr4Tejc/edit
목적
- Pixhawk 소스코드 읽기
- 기존 C개발자가 쉽게 C++ 코드 읽을 수 있게
- Pixhawk에서 자주 사용한 C++ 패턴
- OpenSource 개발자 되기 (http://subak.io/?p=892)
- Embedded에 자주 사용하는 C++
대상
- Pixhawk 관련 개발자
- C/Java 개발자
- Embedded 개발자
- RTOS 개발자
C vs. C++
- C++의 부분집합
- C++ 너무 복잡해요!
- Pixhawk에 사용된 C++에 집중하고 넓혀 나가기
build
- main.cpp 파일 생성
- Build
> g++ main.cpp -std=c++11
- Run
> ./a.out
namespace
- 소스 관리 목적
- 모듈화
- 방법
- 디렉토리 기반
- namespace 기반
namespace
namespace myspace{
void f() {
cout<<"myspace::f();"
}
}
namespace yourspace{
void f() {
cout<<"yourspace::f();"
}
}
namespace
int main()
{
myspace::f();
yourspace::f();
}
namespace
- 찾아보기
- Firmware/src/drivers/device/cdev.cpp
- 실제 사용 예제 찾기
const
- 목적은?
const
class foobar
{
private:
int counter;
public:
void Foo() const
{
cout<<counter++;
}
}
const
- const의 사전적 의미
- 일반적인 사용 예제
- read-access function
const
- class의 method 끝에 사용
- void Foo() const 내부에서 member 변수를 변경할 수 없다.
- 접근은 가능
class A { public: void Foo() const { ... } };
const
- 찾아보기
- Firmware/src/drivers/batt_smbus/batt_smbus.cpp
- 실제 사용 예제 찾기
class
- C와 구별되는 C++의 핵심 기능, 객체지향프로그래밍
- class를 구성하는 것들에 대한 정의 이해
class A
{
public: //접근 제한자
int a; //member data
void foo(); //멤버함수, method
private:
int a1;
void bar();
};
class
- x, y 좌표를 가지는 Point 클래스
class Point
{
priate :
int x, y;
public:
Point(int, int);
int getArea();
};
class
- 찾아보기
- Firmware/src/drivers/airspeed/airspeed.cpp
- 실제 사용 예제 찾기
Friend
- 상속 관계가 아님
- 다른 class의 private나 protected memeber에 접근 가능
class Rectangle {
int width, height;
public:
int area() { return width*height; }
void convert(Square a);
};
void Rectangle::convert(Square a)
{
width = a.side; //친구라고 인정해 줬으니 Square의 private 멤버에 접근 가능
height = a.side;
}
class Square {
friend class Rectangle; //Rectangle은 내 친구야~
private:
int side;
public:
Square(int a): side(a) {}
};
Friend
- 찾아보기
- Firmware/src/drivers/mpu6000/mpu6000.cpp
- 실제 사용 예제 찾기
상속
- public, protected, private
class A
{
private:
int a;
protected:
int b;
private:
int c;
};
class B: public A
{
};
class B: protected A
{
};
class B: private A
{
};
| Base클래스\상속형태 | public | protected | private |
| ------------- |:-------------:| -----:| -----:|
| public 멤버 | public(외부O) | protected | private |
| protected 멤버 | protected | protected | private |
| private 멤버 | X | X | X |
상속
- 찾아보기
- Firmware/src/drivers/airspeed/airspeed.h
- 실제 사용 예제 찾기
Template
- Generic Programming
- 프로그래밍 스타일 중에 하나
- 알고리즘에서 type을 최대한 뒤에 지정하는 방식으로 필요한 시점이 되면 type을 parameter로 지정한다.
- type만 다른 경우 코드 중복을 제거
- 파라미터가 많이 사용되면 코드 읽고 이해하기 어려워진다는 단점
Template 예제
template <typename T>
class Stack
{
private:
vector<T> elems;
public:
void push(T const&);
void pop();
T top() const;
bool empty() const {
return elems.empty();
}
};
void main()
{
Stack<int> intStack;
Stack<string> stringStack;
//....
}
Template
- 찾아보기
- Firmware/src/platforms/px4_message.h
- Firmware/src/modules/uavcan/libuavcan/libuavcan/include/uavcan/node/generic_publisher.hpp
- 실제 사용 예제 찾기
virtual
- 순서 가상함수에서는 A에서 선언하고 이를 상속한 B에서는 반드시 구현부가 있어야 한다.
- 상속 관계에서 method overriding시에 어떤 멤버 method가 호출되는지 이해
virtual 예제
class A
{
public:
virtual int f()=0;
};
class B: public A
{
public:
int f() { return 2; }
};
class C: public A
{
public:
int f() { return 3; }
};
void main()
{
A* a = new A_kind_class;
a->f(); //B or C를 결정하고 적절한 f()를 호출
}
virtual
class Animal
{
pubic:
void eat() { std::cout << "I'm eating generic food.";}
}
class Cat : public Animal
{
public:
void eat() { std::cout << "I'm eating a rat."; }
}
Animal* animal = new Animal;
Cat* cat = new Cat;
animal->eat();
cat->eat();
void func(Animal* xyz) { xyz->eat(); }
func(animal); //"I'm eating generic food."
func(cat); //"I'm eating generic food."
virtual
- 찾아보기
- Firmware/src/drivers/bmp280/bmp280.h
- Firmware/src/drivers/airspeed/airspeed.h
- 실제 사용 예제 찾기
operator overloading
- 함수 호출 대신 연산자만을 이용해서 함수의 동작을 할 수 있도록 하는 문법
- 사용 가능한 operator
- 할당 연산자 : =
- 수치 연산자 : +, -, *
- 복합할당 연산자 : +=, -=,
*=
- 비교 연산자 : ==, !=
operator overloading 예시
class A
{
private:
int x, y;
public:
A operator+(const A& a1, const A& a2);
};
A operator+(const A& a1, const A& a2)
{
A a(a1.x+a2.x, a1.y+a2.y);
return a;
}
void main()
{
A a1(1, 2);
A a2(3, 4);
A a3 = a1 + a2;
//...
}
nullptr
- C++11에서 추가
- NULL vs. nullptr
#define NULL 0 vs. std::nullptr_t
- pointer literal
- nullptr에서 다양한 포인터 타입의 null pointer value로 implicit conversion 가능.
- '진짜 null pointer야!'
nullptr 예시
void f(int *p);
void f(int v);
f(nullptr); // f(int *p) 호출
f(0); // f(int v) 호출
f(NULL); // f(int v) 호출
#include <cstddef>
#include <iostream>
template<class F, class A>
void Fwd(F f, A a)
{
f(a);
}
void g(int* i)
{
std::cout << "Function g called\n";
}
int main()
{
g(NULL); // Fine
g(0); // Fine
Fwd(g, nullptr); // Fine
// Fwd(g, NULL); // ERROR: No function g(int)
}
nullptr
- 찾아보기
- Firmware/src/drivers/airspeed/airspeed.cpp
- 실제 사용 예제 찾기
const_cast
- 함수에서 const가 아닌 인자가 들어가는 자리에 const pointer를 사용할 수 있다.
- const가 아닌 인자를 받는 파라미터에 const 타입을 사용할 수 있다.
- pointer가 가리키는 obj의 const 속성을 보호하기 위해서
const_cast 예제
void print(char *str)
{
//str[0] = 'a'; compile마다 다른 처리. -> 문제상황
cout<<str<<"\n";
}
int main()
{
const char *c = "test";
//print(c); //compile error발생
print(const_cast<char *>(c));
return 0;
}
static_cast
- 관련 class들(상속관계)에 대한 pointer에 대해서 변환 (up/downcast 가능)
- obj가 변환을 보장을 위한 check를 compile time(O), runtime(X) -> 모든게 개발자 책임!
- dynamic_cast의 type안전성 체크의 overhead가 없다. -> embedded에 사용.
- static_cast
( expression ) - http://en.cppreference.com/w/cpp/language/static_cast
class Base {};
class Derived: public Base{};
Base *a = new Base;
Derived *b = static_cast<Derived*>(a);
static_cast
- 찾아보기
- Firmware/src/drivers/rgbled/rgbled.cpp
- Firmware/src/drivers/sf0x/sf0x.cpp
- 실제 사용 예제 찾기
reinterpret_cast
- pointer type을 다른 pointer type으로 변환.(관계 없는 class끼리도 가능)
- 연산 결과는 pointer에서 다른 pointer로 binary 값의 복사가 일어난다.
- 따라서 모든 pointer 변환이 가능하다. 가리키는 내용과 pointer type에 대한 검사를 수행하지 않는다. -> 가장 위험 개발자가 모든 책임을 진다.
- 컴파일러마다 다르므로 주의
class A {};
class B {};
A* a = new A;
B* b = reinterpret_cast<B*>(a);
reinterpret_cast
- 찾아보기
- Firmware/src/drivers/camera_trigger/camera_trigger.cpp
- 실제 사용 예제 찾기