Введение
Я немного растерялся от правильного способа хранения структуры данных нескольких производных классов. Я относительно новичок в C ++, поэтому извините, если у меня есть идиотские ошибки / неправильные представления.
В данный момент я использую vector<Base*>*
, что имеет смысл для меня. Однако я сталкиваюсь с некоторыми проблемами, когда пытаюсь использовать объекты, содержащиеся в векторе.
Проблемы, с которыми я сталкиваюсь
Я собираюсь использовать этот пример, чтобы продемонстрировать свои проблемы:
Base.h
class Base {
public:
Base();
Base(int a, int b);
virtual ~Base();
friend std::ostream& operator<<(std::ostream& os, Base& base);
int getA();
int getB();
protected:
int a;
int b;
};
Derived.h
class Derived : public Base {
public:
Derived(int a, int b, int c);
~Derived();
friend std::ostream& operator<<(std::ostream& os, Derived& derived);
getC();
private:
int c;
};
# 1: Использование функций-членов производных классов
int main() {
vector<Base*>* objects = new vector<Base*>();
Base* newbase = new Base(0, 1);
Derived newderived = new Derived(2, 3, 4);
objects.push_back(newbase);
objects.push_back(newderived);
cout << objects->front()->getA() << endl; // '0'
cout << objects->back()->getA() << endl; // '2'
cout << objects->back()->getC() << endl; // error: 'class Base' has no member named 'getC()'
}
Несмотря на то, что последний объект в objects
является экземпляром класса Derived
, он распознается только как класс Base
. Это, конечно, имеет смысл; objects
удерживать Base*
.
Хотя я понимаю, почему возникает ошибка, я не совсем понимаю, как ее устранить. В моих предыдущих поисках я обнаружил, что есть два обычно предлагаемых (и также довольно спорных) решения: включая каждую функцию-член, которую мои различные производные классы используют в качестве virtual
функции в Base
, и использование статического приведения.
Каков надлежащий метод / хорошая практика для использования функций-членов производных классов внутри структур данных, содержащих Base*
?
# 2: Использование друзей: перегрузка оператора вставки
int main() {
vector<Base*>* objects = new vector<Base*>();
Base* newbase = new Base(0, 1);
Derived newderived = new Derived(2, 3, 4);
objects.push_back(newbase);
objects.push_back(newderived);
cout << *(objects->front()) << endl; // Executed `Base`'s overloaded insertion operator
cout << *(objects->back()) << endl; // Also executed `Base`'s overloaded insertion operator
}
В этом случае я нашел очень мало надежных предложений для решения этой проблемы, за исключением «просто использовать метод print ()». Я понимаю, что могу обойти эту проблему, но я бы лучше понял, как правильно реализовать что-то, чем просто избегать его использования.
Итак, возможно ли каким-либо образом выполнить перегруженный оператор вставки производного класса при вызове из vector<Base*>
? Любая функция друга?
# 3: Определение, к какому производному классу относится объект
int main() {
vector<Base*>* objects = new vector<Base*>();
Derived newderived = new Derived(2, 3, 4);
Derived2 newderived2 = new Derived2(5, 6, 7, 8);
objects.push_back(newderived);
objects.push_back(newderived2);
if (/* objects->front() is a Derived */) cout << "Type check success << endl;
if (/* objects->back() is a Derived2 */) cout << "Type check success << endl;
}
Эта проблема, в частности, была рассмотрена несколько раз ранее. Два решения, которые я видел, так или иначе оценивают то, что происходит после статического приведения, и сохраняют некоторую форму списка типов в базовом классе и сохраняют значение типа во всех производных классах.
Однако, как я упоминал ранее, я новичок в C ++, и я не понимаю первый вариант или правильный способ реализации второго. Как правильно решить эту проблему, и есть ли какие-нибудь объясненные примеры видео или подобные мне для расследования?
Я знаю, что это довольно длинный вопрос, но мне показалось, что все это было настолько тесно взаимосвязано, что я должен держать эти три подвопроса вместе.
Спасибо за помощь!