Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/build
/devel
*/build
*/install
*/log
/.vscode
/src/CmakeLists.txt
*.catkin_workspace
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
# how to use
### build docker environment
- `cd Winter-Tutorial/docker`
- `docker build -t dit/tutorial-ws-noetic:latest .`
- `docker compose up`
- `docker start tutorial-ws-ros1`
- `docker compose up -d`
### open work space
- Attach Visual Studio Code
- `cd tutorial_ws`
- `source /opt/ros/noetic/setup.bash`
- `catkin_make`
- `docker exec -it ros2_tutorial bash`
- `cd ~/ros2_ws`
- `colcon build`
### launch
- `ros2 launch turtle_square_control turtle_launch.py`
38 changes: 38 additions & 0 deletions cpp_oop/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Makefile for C++ OOP Tutorial
# Demonstrates header files, source files, enum, and extern

CXX = g++
CXXFLAGS = -Wall -Wextra -std=c++14 -I./include
TARGET = vehicle_demo

# Source files
SRCS = src/Vehicle.cpp src/Car.cpp src/Airplane.cpp src/main.cpp

# Object files
OBJS = $(SRCS:.cpp=.o)

# Default target
all: $(TARGET)

# Link object files to create executable
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS)
@echo "Build complete! Run with: ./$(TARGET)"

# Compile source files to object files
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@

# Run the program
run: $(TARGET)
./$(TARGET)

# Clean build files
clean:
rm -f $(OBJS) $(TARGET)
@echo "Clean complete!"

# Rebuild everything
rebuild: clean all

.PHONY: all run clean rebuild
110 changes: 110 additions & 0 deletions cpp_oop/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# C++ OOP Tutorial

2025 Winter Turtorial Supplementary C++, OOP的範例程式

## Topics Covered

### 1. OOP (Object-Oriented Programming)
- **Encapsulation**: Private members in `Car` and `Airplane` classes
- **Inheritance**: `Car` and `Airplane` inherit from `Vehicle`
- **Polymorphism**: Virtual function `move()` with different implementations

### 2. Header File (.h) & Source File (.cpp)

#### Header File (`.h`)
- 放 declarations(宣告)、include、extern
- 別人看 header file 就可以知道有什麼功能
- 統一放在資料夾`include`

例如: `Vehicle.h`, `Car.h`, `Airplane.h`

#### Source File (`.cpp`)
- 實際地把 header file 中的東西 implement 出來
- 放在資料夾`src`
- `main.cpp`是主程式,因為只有`main()`所以我沒寫`main.h`

例如: `Vehicle.cpp`, `Car.cpp`, `Airplane.cpp`


### 3. enum (Enumeration)

enum 是一個 user-defined type,代表一組有限的命名整數。


**用途:**
- 劃分不同的類別或狀態
- 讓程式碼更容易閱讀和維護
- 範例 1: Color
- 範例 2: VehicleStatus
- 都在`Vehicle.h`


### 4. Global Variable & extern

**重要規則:**
- extern 只要宣告一次
- 接下來都用 include header file 的方式
- **初始化只要一次**(多個程式嘗試初始化會造成問題!)

**本專案範例:**
- `Vehicle.h`: 宣告 `extern int global_vehicle_count;`
- `Vehicle.cpp`: 初始化 `int global_vehicle_count = 0;`
- `main.cpp`: 透過 include `Car.h` (which includes `Vehicle.h`) 使用這個變數

## Project Structure

```
cpp_oop/
├── include/
│ ├── Vehicle.h # base class + enum + extern 宣告(declaration)
│ ├── Car.h # Car class declaration
│ └── Airplane.h # Airplane declaration
├── src/
│ ├── Vehicle.cpp # Vehicle 實作(implementation) + global 變數初始化
│ ├── Car.cpp # Car implementation
│ ├── Airplane.cpp # Airplane implementation
│ └── main.cpp # 主程式
├── Makefile # 編譯腳本
└── README.md # 本檔案
```

## How to Build and Run

- 由於有多個檔案需要編譯,我叫AI寫了`Makefile`
- `Makefile`可以包含編譯的指令,給`make`工具使用
- 學ROS時會有`CMakeLists.txt`,功能比Makefile更多,編譯過程中會自動生成`Makefile`
- 不需要打開`Makefile`
- 想要自己用`g++`之類的編譯請問AI

### Entering the directory in docker container
```bash
# 以免有人本地端無法編譯C++,這邊的指令是在container裡編譯
# 編譯管道與ROS無關,只是單純的 make工具 與 g++ compiler

### Build docker environement(Same as the homepage READE.md)
- `cd docker`
- docker compose up -d
- *Container ros2_tutorial Running* # expected o/p, dont type
- docker exec -it ros2_tutorial bash

### Enter cpp_oop directory
cd cpp_oop
```

### Using Makefile
```bash
# type the command in terminal

# Build the project
make

# Build and run
make run

# Clean build files
make clean

# Rebuild from scratch
make rebuild
```

23 changes: 23 additions & 0 deletions cpp_oop/include/Airplane.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// to avoid multiple include (include guard)
#ifndef AIRPLANE_H
#define AIRPLANE_H

#include "Vehicle.h"

// Airplane is-a Vehicle, so Airplane inherits from Vehicle just like Car
class Airplane : public Vehicle {
private:
int altitude;

public:
// Constructor of Airplane
Airplane(int fuel, int max_speed, int altitude, Color color = BLUE);

// 除了inherited from Vehicle的public getter/setter function,Airplane還有自己的函式
void climb(int meters);
int getAltitude() const;

std::string move() const override; // declare with override to enable polymorphism
};

#endif
24 changes: 24 additions & 0 deletions cpp_oop/include/Car.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// to avoid multiple include (include guard)
#ifndef CAR_H
#define CAR_H

#include "Vehicle.h" // to use class declaration of Vehicle


// Car is-a Vehicle, so Car inherits from Vehicle
class Car : public Vehicle {
private:
int seat_count; // encapsulated

public:
// Constructor with color parameter
Car(int fuel, int max_speed, int seat_count, Color color = RED);

// 除了inherited from Vehicle的public getter/setter function,Car還有自己的函式
void drive();
int getSeatCount() const;

std::string move() const override; // declare with override to enable polymorphism
};

#endif
60 changes: 60 additions & 0 deletions cpp_oop/include/Vehicle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// to avoid multiple include (include guard)
#ifndef VEHICLE_H
#define VEHICLE_H

#include <string>

// enum: a user-defined type that represents a finite set of named integer
enum Color {
RED, // 預設 RED==0
GREEN, // GREEN==1
BLUE, // BLUE==2
YELLOW,
BLACK,
WHITE
};

// 用來表示交通工具的狀態
enum VehicleStatus {
IDLE = 0,
MOVING = 1,
REFUELING = 2,
MAINTENANCE = 3
};

// 在.h宣告變數extern但不初始化
extern int global_vehicle_count;

// 交通工具(抽象概念)
class Vehicle {
protected:
int fuel; // 燃料
int max_speed; // 最大速度
Color color; // 顏色 (使用 enum)
VehicleStatus status; // 狀態 (使用 enum)

public:
Vehicle(int fuel, int max_speed, Color color = WHITE);
virtual ~Vehicle(); // destructor

void refuel(int amount);

// getter function (get the values of these variables but not directly accessing them)
int getFuel() const; // const -> this function should not modify the variable in the class
int getMaxSpeed() const;
Color getColor() const;
VehicleStatus getStatus() const;

// setter function (set the values of specified varaible)
void setStatus(VehicleStatus new_status);

// demo how to use enum for if-statement
std::string getColorName() const;

// Polymorphism interface, declared virtual
// this is pure virtual function(so the child of Vehicle must declare own move function)
// pure virtual function does not need function definition here
virtual std::string move() const = 0;
};

#endif
23 changes: 23 additions & 0 deletions cpp_oop/src/Airplane.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "Airplane.h"

Airplane::Airplane(int fuel, int max_speed, int altitude, Color color)
: Vehicle(fuel, max_speed, color), altitude(altitude) {}

void Airplane::climb(int meters) {
if (fuel > 0) {
status = MOVING; // 使用 enum 設定狀態
altitude += meters;
fuel--;
}
else {
status = IDLE;
}
}

int Airplane::getAltitude() const {
return altitude;
}

std::string Airplane::move() const {
return "Airplane flies in the sky";
}
24 changes: 24 additions & 0 deletions cpp_oop/src/Car.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "Car.h"
// no need to include Vehicle.h, since Car.h has included Vehicle.h

Car::Car(int fuel, int max_speed, int seat_count, Color color)
: Vehicle(fuel, max_speed, color), seat_count(seat_count) {}
// Car's constructor must call the constructor of the parent(Vehicle)

void Car::drive() {
if (fuel > 0) {
status = MOVING; // 使用 enum 設定狀態
fuel--; // protected member
}
else {
status = IDLE;
}
}

int Car::getSeatCount() const {
return seat_count;
}

std::string Car::move() const {
return "Car drives on the road";
}
Loading