Я программировал некоторое время в школе, и я работаю над своим первым независимым крупным проектом. Я обнаружил много вещей о программировании, которых я не знал раньше, и это было здорово.
Однако, все больше и больше, я чувствую, что я больше не понимаю C ++ как язык, чем больше я в него углубляюсь. Я хотел бы получить некоторые из моих (неправильных) представлений о ссылках и указателях прямо перед тем, как продолжить, и я надеюсь, что вы, stackoverflow, могли бы исправить меня, если я ошибаюсь.
Заранее спасибо, и все!
1. При преобразовании между классами, то, что на самом деле преобразуется, это виртуальная таблица.
Пример:
class A{
public:
A() : x(0) {};
int x;
virtual void doStuff() {
cout << x <<endl;
}
};
class B : public A{
public:
B() : y(1) {};
int y;
virtual void doStuff() {
cout << y <<endl;
}
};
Если бы я преобразовал объект b типа B в A, то что бы произошло внутри, если бы виртуальная таблица b была бы отброшена и заменена соответствующей виртуальной таблица типа A, и деструктор y будет вызван, потому что на него больше нет ссылки. Аналогично, doStuff в b должен указывать на адрес функции A :: doStuff вместо B :: doStuff. Однако адрес, указывающий на x, останется прежним.
2. Это означает, что единственный способ воспользоваться полиморфизмом - это использовать указатели и ссылки.
Как следствие пункта 1, единственный способ воспользоваться преимуществами полиморфизма в виртуальных методах классов - это использовать ссылки и указатели, потому что если мы передается по значению, сами классы будут автоматически преобразованы в базовый класс.
Пример:
void doALotOfStuff(A a1, A a2) {
a1.doStuff();
a2.doStuff();
}
int main(){
A a;
B b;
doALotOfStuff(a,b);
return 0;
}
выведет
0
0
, потому что компилятор сгенерирует код для преобразования b в A.
3. Кроме того, единственный способ воспользоваться преимуществами такого полиморфизма с массивами и контейнерами STL - это использовать указатели, поскольку ссылки не могут быть сохранены
Поскольку вектор не будет работать, поскольку ссылки не присваиваются, из этого следует, что если бы я хотел иметь вектор базовых классов, мне нужно было бы создать вектор указателей на A, чтобы сохранить виртуальную таблицу элементов типа B.
Извините, если это был TL; DR, но мне было бы неприятно в то время как я занимался дизайном классов для своего проекта и понял, что не могу из-за проблем с интерфейсами библиотек и проблемами полиморфизма уйти от простого использования либо указателей, либо ссылок.