Ссылка на указатели и полиморфизм C++

OnSwipeTouchListener.java:

import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class OnSwipeTouchListener implements OnTouchListener {

    private final GestureDetector gestureDetector = new GestureDetector(new GestureListener());

    public boolean onTouch(final View view, final MotionEvent motionEvent) {

        super.onTouch(view, motionEvent);
        return gestureDetector.onTouchEvent(motionEvent);

    }

    private final class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            onSwipeRight();
                        } else {
                            onSwipeLeft();
                        }
                    }
                } else {
                    if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffY > 0) {
                            onSwipeBottom();
                        } else {
                            onSwipeTop();
                        }
                    }
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }
    public void onSwipeRight() {}
    public void onSwipeLeft() {}
    public void onSwipeTop() {}
    public void onSwipeBottom() {}
}

ИСПОЛЬЗОВАНИЕ:

imageView.setOnTouchListener(new OnSwipeTouchListener() {

    public void onSwipeTop() {
        Toast.makeText(MyActivity.this, "top", Toast.LENGTH_SHORT).show();
    }
    public void onSwipeRight() {
        Toast.makeText(MyActivity.this, "right", Toast.LENGTH_SHORT).show();
    }
    public void onSwipeLeft() {
        Toast.makeText(MyActivity.this, "left", Toast.LENGTH_SHORT).show();
    }
    public void onSwipeBottom() {
        Toast.makeText(MyActivity.this, "bottom", Toast.LENGTH_SHORT).show();
    }

});
11
задан 22 May 2009 в 17:23
поделиться

5 ответов

Параметр ppObj для RemoveObj является ссылкой на родительский *. Что, если метод RemoveObj () заменит указатель указателем на новый объект Parent ? Когда метод вернул ваш pCObj Child * , больше не будет указывать на объект Child .

16
ответ дан 3 December 2019 в 06:47
поделиться

Из стандарта C ++ (1998)

За исключением контекста инициализация определенным пользователем преобразование (13.3.1.4, 13.3.1.5), a правильно сформированное неявное преобразование последовательность является одной из следующих формы: - стандартное преобразование последовательность (13.3.3.1.1), -a пользователь определено ...

13.3.3.1.1

Не более одного преобразования от каждого категория разрешена в единственном стандартная последовательность преобразования

Таким образом, c ++ НЕ может выполнять неявное преобразование два раза подряд: из указателя в указатель, а затем снова из указателя.

Чтобы прояснить это, рассмотрите такое объявление RemoveObj

void RemoveObj(Parent ** ppObj)

И вы увидите эту ошибку

error: invalid conversion from 'Child**' to 'Parent**'

Вы должны использовать явное преобразование, например

   RemoveObj((Parent**)&pCObj);
   RemoveObj((Parent*&)&pCObj);

, или изменить

void RemoveObj(Parent *& ppObj)

на

void RemoveObj(Parent * ppObj)

или на

template <typename T>
void RemoveObj(T *& pObj)
{
   delete pObj;
   pObj = 0;
}
4
ответ дан 3 December 2019 в 06:47
поделиться

ppobj - это ссылка для указателя. * ppobj разыменовывает то, на что указывает переменная, поэтому вы получаете переменную указателем.

Поскольку разыменование не правильного типа, вы видите ошибку.

0
ответ дан 3 December 2019 в 06:47
поделиться

Это не является достоверным, но я считаю, что проблема в том, что полиморфная природа классов C ++ не распространяется на их указатели; здесь вы ожидаете, что Дочерний * будет приведен к Родителю * ; хотя вы можете преобразовать дочерний в родительский , вы не можете преобразовать указатель ссылку . То есть классы полиморфны, но указатели на классы не являются ссылками. Это по той причине, которую Майкл Берр приводит выше; Дочерний * подразумевает определенную структуру памяти, в отличие от Родителя * .

-2
ответ дан 3 December 2019 в 06:47
поделиться

Указатель на ссылку позволяет изменять значение указателя в функции. Как отмечает Майкл Барр, существует возможность присвоить некорректную ссылку на класс и вернуть ее. Представьте себе всю вашу программу, некорректно использующую *pchickens в качестве *peggs :)

Я подумал, что это стоит добавить (хотя явно не то, что вы просили): Мое предпочтение в полиморфной реализации заключается в переносе внутри общих функций в качестве методов. Если они все разделяют функцию, просто добавьте ее в базовый класс.

Тогда в любом случае вы можете просто вызвать Foo->Bar() и достичь желаемого результата. Но для конкретного примера реализации, который вы приводите, просто удалить Foo вызовет соответствующий деструктор.

0
ответ дан 3 December 2019 в 06:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: