Betrachten Sie den folgenden Code-Schnipsel:Wie kann ich einen virtuellen Anruf vermeiden, wenn ich den Typ kenne?
struct Base { virtual void func() { } };
struct Derived1 : Base { void func() override { print("1"); } };
struct Derived2 : Base { void func() override { print("2"); } };
class Manager {
std::vector<std::unique_ptr<Base>> items;
public:
template<class T> void add() { items.emplace_back(new T); }
void funcAll() { for(auto& i : items) i->func(); }
};
int main() {
Manager m;
m.add<Derived1>();
m.add<Derived2>();
m.funcAll(); // prints "1" and "2"
};
Ich virtual
Versand, um mit der richtigen override
Methode aus einem std::vector
polymorphen Objekten zu nennen.
Allerdings weiß ich, welchen Typ die polymorphen Objekte sind, da ich dies in Manager::add<T>
angeben.
Meine Idee war es, einen virtual
Anruf zu vermeiden, indem Sie die Adresse der Mitgliedsfunktion T::func()
nehmen und direkt irgendwo speichern. Das ist jedoch unmöglich, da ich es als void*
speichern und in Manager::funcAll()
zurückgeben müsste, aber ich habe in diesem Moment keine Typinformationen.
Meine Frage ist: es scheint, dass ich weitere Informationen in dieser Situation für Polymorphismus als üblich habe (der Benutzer gibt den abgeleiteten Typen T
in Manager::add<T>
) - ist es eine Möglichkeit, diese Art Informationen verwenden, um ein scheinbar unnötigen virtual
zu verhindern Anruf? (Ein Benutzer sollte in der Lage sein, ihre eigenen Klassen zu erstellen, die von Base
in seinem Code ableiten, aber.)
"Gibt es eine Möglichkeit, diese Art von Informationen zu verwenden, um einen scheinbar unnötigen virtuellen Anruf zu verhindern?" Lösche diese Information nicht? ('unique_ptr ' tippt hier das Löschen ein). In jedem Fall "die Adresse der Member-Funktion' T :: func() 'zu nehmen und sie direkt irgendwo zu speichern" ist so ziemlich das Gleiche wie ein virtueller Aufruf, außer mit viel mehr Arbeit von Ihrer Seite. –
@ R.MartinhoFernandes: Ich verstehe. Ich sehe jedoch keine andere Möglichkeit, Typen zu speichern, die von 'T' abstammen, selbst nach Angabe des Typs in' Manager :: add '- denken Sie daran, dass der Benutzer seine eigenen Typen definieren soll, die von' Base' abgeleitet sind Ich weiß nicht, was diese Typen sein werden. –
Also, was Sie wollen, ist in der Sprache einfach unmöglich zu erreichen (ein Compiler könnte jedoch eine solche Optimierung in diesem Beispielcode vornehmen, aber ich bezweifle, dass Sie das in der Praxis finden). Es ist eine klassische "Sie können Ihren Kuchen nicht essen und haben es auch" -Situation: Entweder löschen Sie die Typen, oder Sie behalten die Typen. –