Every team that grows past one mechanism hits the same wall: main.cpp becomes 500 lines of chaos. Splitting code into subsystem files makes it readable, maintainable, and debuggable — skills that transfer directly to real-world software engineering.
A well-organized VRC project looks like this:
Each subsystem has exactly two files: a .cpp file with the actual code, and a .hpp header file that declares what functions exist. Any other file that needs the intake just includes the header — it does not need to know how the intake works internally.
#pragma once is a header guard. It tells the compiler: "only include this file once, even if multiple other files include it." Without it, if both main.cpp and arm.cpp include intake.hpp, the compiler sees the declarations twice and throws a duplicate definition error.
Always put #pragma once as the very first line of every .hpp file you create. It is simpler than the older #ifndef/#define/#endif pattern and works in all modern compilers including PROS.
static at the top of the .cpp.main.cpp is now clean and readable. It describes what happens during a match — not how each mechanism works. The how lives in each subsystem file.
static keyword on intakeRunning means it is private to intake.cpp. No other file can access or accidentally modify it. This is encapsulation — the same concept taught in every computer science course. Use static on any variable or helper function that should not be visible outside the file.In EZ Template projects, motors and sensors are typically declared in robot-config.cpp. When intake.cpp tries to call intake.move(127), the compiler asks: what is intake? Where was it declared?
There are two clean solutions:
In EZ Template projects, motor objects are typically declared in robot-config.cpp and already accessible via main.h. Check your project's main.h — if the motors are declared there or in a header it includes, your subsystem .cpp files can access them by just including main.h.
If you add a new motor that is not in main.h, declare the motor object in robot-config.cpp and add an extern declaration to your subsystem header:
extern is a declaration — it says the object exists elsewhere. The actual object should only be created (defined) in one place, typically robot-config.cpp. Creating it twice causes a "multiple definition" linker error.pros::Motor intake(3); — creates the object. Do this once.extern pros::Motor intake; — tells other files it exists. Do this in headers.#pragma once implements an include guard: a compile-time mechanism to prevent duplicate declarations when a header is included by multiple files.pros::Motor arm(5); in arm.cpp. Your auton.cpp needs to use the arm motor. What is the correct approach?extern pros::Motor arm; in arm.h, include arm.h in auton.cpp — this tells the linker the variable exists elsewhere without creating a duplicate