One function for multiple classes to use.

I have a regular complicate shunting function I have in a separate h&cpp file.

#ifndef Shunt_h
#define Shunt_h

#include <ctype.h>
#include <Arduino.h>

#define MAXOPSTACK 64
#define MAXNUMSTACK 64


float eval_add(float a1, float a2);
float eval_sub(float a1, float a2);
float eval_uminus(float a1, float a2);
float eval_exp(float a1, float a2);
float eval_mul(float a1, float a2);
float eval_div(float a1, float a2);

float eval_mod(float a1, float a2);
struct operator_type *getop(char ch);
void push_opstack(struct operator_type *op);
struct operator_type *pop_opstack();
void push_numstack(float num);
float pop_numstack();
void shunt_op(struct operator_type *op);
int isdigit_or_decimal(int c);
float shuntThis(char *in_formula);

#endif

I have classes that use this function.
I simply #include <Shunt.h> and call shuntThis(newFormula) in the class.

float Analog::getNewValue() {

    char buffer[10];
    strcpy(analogValue, itoa(analogRead(pin),buffer,10));
    
    if(strcmp(formula,"") != 0) {
        searchAndReplace(var, analogValue);
    }
    
    float temp = 0.0;
    if(strcmp(newFormula,"") != 0) {
        temp = shuntThis(newFormula);
    }

    return temp;
    
}

It works but is this good practice? I don't make an Shunt into an object. My main worry is memory management.

Does the Shunt code have any global variables?

MarkT:
Does the Shunt code have any global variables?

All local variables. I just pass in the string formula and let the functions do their thing and return a value.

It works but is this good practice?

Yes.

I don't make an Shunt into an object.

You don't have a class, so you can't create an instance of the class.

My main worry is memory management.

Why?

    if(strcmp(formula,"") != 0) {

That is a piss-poor way of determining whether formula is an empty string. strlen() will tell you the length of the string.