void Pile::grow(Stone s)
You are not using s anywhere. Are you supposed to add it to the new array you are trying to create?
Stone temp[getLength() + 1];
This is not legal in standard C++. The size of a fixed array must be known at compile time.
Some compilers support "variable length arrays" as a non-standard extension, but do not rely on them if you need to write portable code. See Why aren't variable-length arrays part of the C++ standard?
To allocate an array dynamically at runtime, use the new[] operator instead, eg:
Stone *temp = new Stone[getLength() + 1];
...
delete[] temp;
Or, use the standard std::vector container instead, eg:
#include <vector>
std::vector<Stone> temp(getLength() + 1);
...
for (int i = 0; i < sizeof(temp) / sizeof(temp[0]); ++i)
You cannot use this sizeof trick on a dynamic array, let alone a VLA. sizeof is evaluated only at compile time, not at runtime.
Since you are copying values from an existing array, use the length of that array instead:
for (int i = 0; i < getLength(); ++i)
if (sizeof(temp) / sizeof(temp[0]) < 28)
Hard-coding a 28 here makes no sense. In fact, this whole if check needs to be removed completely.
stoneArr = temp;
This assignment will not work when temp is a VLA. And stoneArr can't be a VLA anyway.
stoneArr needs to be either a Stone* pointer to a new[]'d array (that is managed by following the Rule of 3/5/0), or a std::vector<Stone> (preferred).
With all of that said, try this instead:
private:
    Stone *stoneArr;
    int arrLength;
...
Pile::Pile()
    : stoneArr(NULL), arrLength(0) {
}
Pile::Pile(const Pile &src)
    : stoneArr(new Stone[src.arrLength]), arrLength(src.arrLength) {
    for (int i = 0; i < arrLength; ++i) {
        stoneArr[i] = src.stoneArr[i];
    }
}
Pile::~Pile() {
    delete[] StoneArr;
}
Pile& Pile::operator=(const Pile &rhs) {
    if (&rhs != this) {
        Pile temp(rhs);
        std::swap(stoneArr, temp.stoneArr);
        std::swap(arrLength, temp.arrLength);
    }
    return *this;
}
int Pile::getLength() const {
    return arrLength;
}
void Pile::grow(const Stone &s){
    Stone *temp = new Stone[arrLength  + 1];
    for (int i = 0; i < arrLength; ++i) {
        temp[i] = stoneArr[i];
    }
    temp[arrLength] = s;
        
    delete[] stoneArr;
    stoneArr = temp;
    ++arrLength;
}
Or:
#include <vector>
private:
    std::vector<Stone> stoneArr;
...
// std::vector follows the rule of 3/5/0, so let the
// compiler handle Pile(), Pile(const Pile &), ~Pile(),
// and operator= for you...
int Pile::getLength() const {
    return stoneArr.size();
}
void Pile::grow(const Stone &s){
    stoneArr.push_back(s);
}