Matrix(size_t c, size_t r)
: m_matrix(r, std::vector<T>(c, T()))
, cols{ c }
, rows{ r }
{
}
int* p = new int[100]; p++; delete[] p;
ты сознательно допускаешь утечку памяти, что плохо, но не смертельно. Сделав то же самое для int p[100]
, ты получил бы порчу стека.
Если хочется быстро, чтобы работало как-нибудь, то да, как функцию-член.
Если хочется правильно и код пишется в учебных целях - то да, нужно делать два наследника, HexString, OctString, которые содержат в конструкторе и присваивании проверки на корректность, после чего глобально перегружать operator+ для них, например так:
А в классах указать, что эти операторы дружат с ними, чтобы можно было обращаться к приватным членам.
Ещё можно добавить поддержку операторов приведения типа (https://en.cppreference.com/w/cpp/language/cast_op... которые бы позволяли приводить HexString в OctString и наоборот.
Скорее всего пригодится почитать про forward declaration (https://ru.wikipedia.org/wiki/Предварительное_объя...
Если хочется вообще заморочиться и убить кучу времени на отладку, то можно сделать шаблонный класс, что-нибудь вроде
NumericString<N>
для обобщённого представления строки-числа с произвольным основанием.