This advice is more general, rather than being specific to fighting games, but typically player behaviour in games with any reasonable level of complexity will be coded as a finite state machine, where the different actions that the player can perform (normal locomotion, climbing over objects, melee attacks), are encoded as mutually exclusive "states" that encapsulate that action.
(Edit: This article has a more game-specific explanation of how finite state machines are often used in player code
These states drive player animation and movement, and triggering the consequences of those actions (inflicting damage on enemies when you reach a certain point in the animation, triggering visual effects, etc). The player can be in one state, and only ever one state at a time, and each state can only transition to certain other states.
This kind of approach generally makes more sense than implementing as functions, because typically your player is going to be in one of these states for longer than a single frame, and this is a natural way to handle that more long-lived state. For example, if the player performs a heavy attack, you might want to keep them locked into that animation/state until a certain point has been reached, for balancing purposes but also to give the action a real sense of weight and consequence.
It also makes things easier to reason about, if you ever decide to implement networked multiplayer, because then it becomes much easier to think about what information you need to replicate to other players.
One thing I would caution against though, is making heavy use of class inheritance when writing this code. It becomes a massive pain if at some point in the future you want to share functionality between states that aren't otherwise related. Then you end up pushing functionality into some base class where it doesn't belong and messing up the code.. or having to duplicate bug fixes in several different player state classes that end up being almost complete copy-pastes of one another with a few things changed.
For a melee attack state for example, your different attacks might be conceptually similar enough to one another, that it makes sense to have one melee attack state, and just drive the different attack types based on the "start parameters" that the state was given when it started.
Consequences like inflicting damage, can usually be written into some kind of common utils function that's called from various places, and called internally from within your state.
If you're careful not to put too much player-input specific logic in your state machine code, it also comes in handy if you find you want to implement AI that can play your game at some point in the future, as they can reuse a lot of the same player state machine code to drive their animations/actions. (It's just that the actions being requested are coming from the AI now, instead of directly from an input device)