Встроенные виртуальные функции являются действительно ерундой?

По моему мнению, если вы хотите управлять своей анимацией, а не просто анимировать ее, я рекомендую вам использовать js для управления стилем вашего элемента. Потому что animation это завершить серию анимации.

И есть действительно мощный CSS, называемый переменной css, вы можете получить более подробную информацию о https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties . [119 ]

const rotate=document.getElementById("rotate")
let r=0
rotate.addEventListener("click",()=>{
  r += 10
  rotate.style.setProperty("--rotate", r+"deg");
})
#rotate{
  --rotate:0deg;
  background:pink;
  width:100px;
  height:100px;
  transform:rotate(var(--rotate));
  transition:transform 1s;
}

click the square and then it will rotate.

Конечно, если вы хотите серию анимаций, вы можете проверить это на https : //developer.mozilla.org/en-US/docs/Web/CSS/animation . Это легко установить шаги в анимации.

167
задан Kara 8 July 2013 в 17:43
поделиться

7 ответов

Виртуальные функции иногда могут быть встроены. Отрывок из превосходного C ++ faq :

«Единственный раз, когда встроенный виртуальный вызов может быть встроено, когда компилятор знает "точный класс" объекта которая является целью виртуального вызов функции. Это может случиться только когда у компилятора есть фактический объект а не указатель или ссылка на объект. То есть либо с местным объект, глобальный / статический объект или полностью содержащий объект внутри композитный. "

144
ответ дан Wumpf 23 November 2019 в 21:00
поделиться

Я видел компиляторы, которые не генерируют v-таблицы, если вообще не существует не встроенной функции ( и определяется в одном файле реализации вместо заголовка). Они будут выдавать ошибки, такие как , пропуская vtable-for-class-A или что-то подобное, и вы будете в замешательстве, как и я.

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

Как кто-то упоминал, встроенные виртуальные функции могут быть полезны иногда , но, конечно, чаще всего вы будете использовать его, когда не не знаете динамический тип объекта, потому что это было главной причиной виртуального в первую очередь.

Однако компилятор не может полностью игнорировать inline . У этого есть другая семантика кроме ускорения вызова функции. Неявный встроенный для определений в классе - это механизм, который позволяет поместить определение в заголовок: только встроенные функции могут быть определены несколько раз по всей программе без нарушения какой-либо правила. В конце концов, он ведет себя так, как вы бы определили его только один раз во всей программе, даже если вы включили заголовок несколько раз в разные файлы, связанные вместе.

потому что это было главной причиной виртуального в первую очередь.

Однако компилятор не может полностью игнорировать inline . У этого есть другая семантика кроме ускорения вызова функции. Неявный встроенный для определений в классе - это механизм, который позволяет поместить определение в заголовок: только встроенные функции могут быть определены несколько раз по всей программе без нарушения какой-либо правила. В конце концов, он ведет себя так, как вы бы определили его только один раз во всей программе, даже если вы включили заголовок несколько раз в разные файлы, связанные вместе.

потому что это было главной причиной виртуального в первую очередь.

Однако компилятор не может полностью игнорировать inline . У этого есть другая семантика кроме ускорения вызова функции. Неявный встроенный для определений в классе - это механизм, который позволяет поместить определение в заголовок: только встроенные функции могут быть определены несколько раз по всей программе без нарушения какой-либо правила. В конце концов, он ведет себя так, как вы бы определили его только один раз во всей программе, даже если вы включили заголовок несколько раз в разные файлы, связанные вместе.

Неявный встроенный для определений в классе - это механизм, который позволяет поместить определение в заголовок: только встроенные функции могут быть определены несколько раз по всей программе без нарушения какой-либо правила. В конце концов, он ведет себя так, как вы бы определили его только один раз во всей программе, даже если вы включили заголовок несколько раз в разные файлы, связанные вместе.

Неявный встроенный для определений в классе - это механизм, который позволяет поместить определение в заголовок: только встроенные функции могут быть определены несколько раз по всей программе без нарушения какой-либо правила. В конце концов, он ведет себя так, как вы бы определили его только один раз во всей программе, даже если вы включили заголовок несколько раз в разные файлы, связанные вместе.

14
ответ дан Johannes Schaub - litb 23 November 2019 в 21:00
поделиться

inline действительно ничего не делает - это подсказка. Компилятор может игнорировать его или встроить событие вызова без встроенного встроенного , если он видит реализацию и ему нравится эта идея. Если на карту поставлена ​​ясность кода, следует удалить строку .

3
ответ дан sharptooth 23 November 2019 в 21:00
поделиться

С современными компиляторами это не принесет никакого вреда, чтобы их не включить. Некоторые древние комбинации компилятора и компоновщика могли создать несколько vtables, но я не думаю, что это больше проблема.

1
ответ дан 23 November 2019 в 21:00
поделиться

В случаях, когда вызов функции однозначен и функция является подходящим кандидатом для встраивания, компилятор достаточно умен, чтобы в любом случае, встроенный код.

В остальное время «встроенный виртуальный» - это нонсенс, и, действительно, некоторые компиляторы не будут компилировать этот код.

1
ответ дан moonshadow 23 November 2019 в 21:00
поделиться

Компилятор может встроить функцию только тогда, когда вызов может быть однозначно разрешен во время компиляции.

Виртуальные функции, однако разрешаются во время выполнения, и поэтому компилятор не может встроить вызов, поскольку при типе компиляции динамический тип (и, следовательно, вызываемая реализация функции) не может быть определен.

1
ответ дан Jonathan Leffler 23 November 2019 в 21:00
поделиться

Существует одна категория виртуальных функций, в которой все еще имеет смысл иметь встроенные функции. Рассмотрим следующий случай:

class Base {
public:
  inline virtual ~Base () { }
};

class Derived1 : public Base {
  inline virtual ~Derived1 () { } // Implicitly calls Base::~Base ();
};

class Derived2 : public Derived1 {
  inline virtual ~Derived2 () { } // Implicitly calls Derived1::~Derived1 ();
};

void foo (Base * base) {
  delete base;             // Virtual call
}

При вызове delete 'base' будет выполнен виртуальный вызов для вызова корректного деструктора производного класса, этот вызов не является встроенным. Однако, поскольку каждый деструктор вызывает свой родительский деструктор (который в этих случаях пуст), компилятор может встроить эти вызовы , поскольку они виртуально не вызывают функции базового класса.

Тот же принцип существует для base конструкторы классов или для любого набора функций, где производная реализация также вызывает реализацию базовых классов.

36
ответ дан Richard Corden 23 November 2019 в 21:00
поделиться
Другие вопросы по тегам:

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