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();
}
});
Параметр ppObj
для RemoveObj является ссылкой на родительский *. Что, если метод RemoveObj ()
заменит указатель указателем на новый объект Parent
? Когда метод вернул ваш pCObj
Child *
, больше не будет указывать на объект Child
.
Из стандарта 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;
}
ppobj - это ссылка для указателя. * ppobj разыменовывает то, на что указывает переменная, поэтому вы получаете переменную указателем.
Поскольку разыменование не правильного типа, вы видите ошибку.
Это не является достоверным, но я считаю, что проблема в том, что полиморфная природа классов C ++ не распространяется на их указатели; здесь вы ожидаете, что Дочерний *
будет приведен к Родителю *
; хотя вы можете преобразовать дочерний
в родительский
, вы не можете преобразовать указатель ссылку . То есть классы полиморфны, но указатели на классы не являются ссылками. Это по той причине, которую Майкл Берр приводит выше; Дочерний *
подразумевает определенную структуру памяти, в отличие от Родителя *
.
Указатель на ссылку позволяет изменять значение указателя в функции. Как отмечает Майкл Барр, существует возможность присвоить некорректную ссылку на класс и вернуть ее. Представьте себе всю вашу программу, некорректно использующую *pchickens в качестве *peggs :)
Я подумал, что это стоит добавить (хотя явно не то, что вы просили): Мое предпочтение в полиморфной реализации заключается в переносе внутри общих функций в качестве методов. Если они все разделяют функцию, просто добавьте ее в базовый класс.
Тогда в любом случае вы можете просто вызвать Foo->Bar() и достичь желаемого результата. Но для конкретного примера реализации, который вы приводите, просто удалить Foo вызовет соответствующий деструктор.