How should I code units in an RTS game?

You shouldn’t care about what type of unit they are. They should all share a common parent class, which would be “AUnit”. What you need to do is treat your AUnit class as an abstract class. Have methods that are pure virtual methods and for every class that inherits from AUnit, they will implement these pure virtual methods how they wish. You have an array or AUnit objects and you just let the polymorphism do its work.

class AUnit
{
public:
    virtual void MoveXDirection(float dir) = 0;
    virtual void MoveYDirection(float dir) = 0;
    virtual void Attack() = 0;
    virtual void UseSpecial() = 0;
}

class ASniperUnit : AUnit
{
    virtual void MoveXDirection(float dir)
    {
        // Look at the walkSpeed for this unit, among other vars, and decide 
        how this unit should move in the x-direction.
    }
    virtual void MoveYDirection(float dir)
    {
        // Look at the walkSpeed for this unit, among other vars, and decide 
        how this unit should move in the Y-direction.
    }
    virtual void Attack()
    {
        // Look at the damageVal for this unit, among other vars, and decide 
        how this unit should attack and the damage is should output (before
        external modifiers, maybe the other players armor)
    }
    virtual void UseSpecial()
    {
        // Look how the special move effects this unit.
    }
}

class ASoldierUnit : AUnit
{
    virtual void MoveXDirection(float dir)
    {
        // Look at the walkSpeed for this unit, among other vars, and decide 
        how this unit should move in the x-direction.
    }
    virtual void MoveYDirection(float dir)
    {
        // Look at the walkSpeed for this unit, among other vars, and decide 
        how this unit should move in the Y-direction.
    }
    virtual void Attack()
    {
        // Look at the damageVal for this unit, among other vars, and decide 
        how this unit should attack and the damage is should output (before
        external modifiers, maybe the other players armor)
    }
    virtual void UseSpecial()
    {
        // Look how the special move effects this unit.
    }
}

So you’re on the right track. You want to keep an array of your units that you have selected, or even if you are selecting one individually you would just have an array of 1. You will work on all of you units at the highest level possible (AUnit). Here is some sudo:

list<AUnit> selectedUnits;

void OnUnitsSelected()
{
    // populate your list
}

void OnMoveUnits(Vector2 direction)
{
    foreach AUnit in selectedUnits : myCurUnit
    {
        myCurUnit->MoveXDirection(direction.x);
        myCurUnit->MoveYDirection(direction.y);
    }
}

void OnAttack()
{
    foreach AUnit in selectedUnits : myCurUnit
    {
        myCurUnit->Attack();
    }
}