Есть два способа наладить динамический 2D-массив: «хребет» и «линейный массив».
Хребет определяется как int** a = new int*[m];
А затем каждый элемент хребта присваиваете new.
Доступ a[i][j].
Линейный массив определяется int* a = new int[m*n];
Доступ a[i*n + j].
Ваш случай — линейный массив, то есть
void func(int a[], int n, int m)
…
func(a[0], n, m);
Советую как-то заинкапсулировать эти массивы и передавать
void dumpArray(const Array2D& x)
К сожалению, у инкапсулированного массива нет хорошего способа сделать a[i][j], но можно a(i,j).