Ich habe in letzter Zeit meine Kenntnisse über C++ aktualisiert und aktualisiert, und das Erlernen von strengem Aliasing hat mich ein wenig davor gewarnt, Zeiger von einem Typ auf einen anderen zu übertragen. Ich weiß, dass dies folgende Codebeispiel auf meinem Compiler in der Praxis funktioniert, aber ich möchte sicherstellen, dass es den aktuellen Normen und Richtlinien entspricht:Ist es in Ordnung, eine pointer-to-member-Variable in diesem Fall zu erzeugen?
#include <iostream>
using namespace std;
class MyBase {
public:
virtual void DoSomething() = 0;
};
class MyDerived1 : public MyBase {
public:
virtual void DoSomething() {
cout << "I'm #1" << endl;
}
};
class MyDerived2 : public MyBase {
public:
virtual void DoSomething() {
cout << "I'm #2" << endl;
}
};
template <typename Base, typename Member1, typename Member2>
struct Tuple {
public:
Base* Get(int i) {
return &(this->*(lookupTable[i]));
}
private:
Member1 member1;
Member2 member2;
static Base Tuple::* const lookupTable[2];
};
template <typename Base, typename Member1, typename Member2>
Base Tuple<Base, Member1, Member2>::* const Tuple<Base, Member1, Member2>::lookupTable[2] = {
reinterpret_cast<Base Tuple<Base, Member1, Member2>::*>(&Tuple::member1),
reinterpret_cast<Base Tuple<Base, Member1, Member2>::*>(&Tuple::member2)
};
int main() {
Tuple<MyBase, MyDerived1, MyDerived2> tuple;
tuple.Get(0)->DoSomething();
tuple.Get(1)->DoSomething();
return 0;
}
Im Wesentlichen ist diese einfache Tupel ein Paar Elemente enthält, von denen jeder ableiten sollte aus einer gemeinsamen Basisklasse. Die Get-Funktion gibt eine Base*
an das Element zurück, das der angegebene Index darstellt.
Der Schlüsselteil, über den ich mich wundere, ist die reinterpret_casts. Ich weiß, dass Gießen von Derived Struct::*
bis Base Struct::*
ist im Allgemeinen ein Nein-Nein, aber in diesem Fall verwende ich nur die Zeiger-zu-Mitglied-Variable, um einen Zeiger auf das Objekt zu erhalten. (Ich versuche nicht, ein abgeleitetes Objekt so zu kopieren, als ob es ein Basisobjekt wäre, oder ein Basisobjekt in den Speicher eines abgeleiteten Objekts zu stopfen.) Dies funktioniert auf G ++ wie beabsichtigt, und ich möchte nur sicher sein, dass ich es nicht bin dafür von jedem Compiler kompromittiert werden.
Ich hatte auch diesen Gedanken, aber mein Hauptgrund für dieses komplizierte Setup ist es, so wenige Funktionsaufrufe wie möglich zu erreichen. Ich kann dies als letzten Ausweg tun, aber ich hoffe, dass jemand einen (konformen) Weg kennt, dies zu erreichen, ohne einen Funktionsaufruf zu benötigen. – nonoitall