Получение моих представлений об указателях и ссылках прямо

Я программировал некоторое время в школе, и я работаю над своим первым независимым крупным проектом. Я обнаружил много вещей о программировании, которых я не знал раньше, и это было здорово.

Однако, все больше и больше, я чувствую, что я больше не понимаю 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, но мне было бы неприятно в то время как я занимался дизайном классов для своего проекта и понял, что не могу из-за проблем с интерфейсами библиотек и проблемами полиморфизма уйти от простого использования либо указателей, либо ссылок.

5
задан Lightness Races with Monica 18 January 2013 в 18:28
поделиться