Frage

Der gehorchen, zurückzuweisen reduziert Codebeispiel tut nichts nützlich, sondern zwei nachfolgende Zuweisungen zu einem Datenelementzeiger. Die ersten assignement funktioniert, gibt der zweite einen Compiler-Fehler. Vermutlich, weil sie zu einem verschachtelten Elemente.

Frage wäre: Ist es wirklich einfach nicht möglich, einen Elementzeiger Punkt zu einem verschachtelten Mitglied zu lassen oder bin ich dabei jeden Wunsch Syntax gibt

struct Color {
    float Red;
    float Green;
    float Blue; };


struct Material {
    float Brightness;
    Color DiffuseColor; };


int main() {
    float Material::* ParamToAnimate;
    ParamToAnimate = &Material::Brightness;       // Ok
    ParamToAnimate = &Material::DiffuseColor.Red; // Error! *whimper*
    return 0; }

ATM Ich arbeite mit Hilfe Byteversätze und viele Würfe um. Aber das ist hässlich, würde ich besser wie diejenigen Mitglieds Zeiger zu verwenden.

Ja, ich weiß, diese Frage sicherlich arised vor (wie fast jede Frage). Ja, ich gesucht vorher fand aber keine befriedigende Antwort.

Vielen Dank für Ihre Zeit.

War es hilfreich?

Lösung

AFAIK ist dies nicht möglich. Ein Zeiger-to-Mitglied kann nur durch einen Ausdruck des Typs &qualified_id gebildet werden, was nicht der Fall ist.

Vite Falcon-Lösung ist wahrscheinlich die am besten geeignet.

Andere Tipps

Ich nehme an, Sie versuchen, den Zeiger auf die Datamember Red zu bekommen. Da dies in dem struct Color definiert ist, ist die Art des Zeigers Color::*. Daher sollten Sie den Code sein:

int main() {
    float Color::* ParamToAnimate;
    ParamToAnimate = &Color::Red; 
    return 0; }

Um es zu nutzen, müssen Sie es auf eine Instanz Color zum Beispiel binden:

void f(Color* p, float Color::* pParam)
{
    p->*pParam = 10.0;
}
int main() {
    float Color::* ParamToAnimate;
    ParamToAnimate = &Color::Red; 

    Material m;
    f(&m.DiffuseColor, ParamToAnimate);
    return 0;
}

Bearbeiten : Ist es nicht möglich, die Animationsfunktion einer Vorlage zu machen? Zum Beispiel:

template<class T>
void f(T* p, float T::* pParam)
{
    p->*pParam = 10.0;
}
int main() {

    Material m;

    f(&m.DiffuseColor, &Color::Red);
    f(&m, &Material::Brightness);
    return 0;
}

Statt eines Mitglieds Zeiger, können Sie einen Funktor, dass die Renditen ein float* verwenden, wenn eine Instanz von Material gegeben; ändert die Art der ParamToAnimate zu so etwas wie:

std::function<float*(Material&)>

Auf der positiven Seite, es ist tragbar -. Aber auf der Kehrseite, es erfordert eine erhebliche Menge an Standardcode und hat signifikanten Laufzeitaufwand

Wenn diese Leistung entscheidend ist, würde ich mit der Offset-Methode Stick versucht werden.

Im Grunde versucht man, einen Zeiger auf eine Variable vom Typ float zu bekommen, dass Sie animieren können. Warum float* nicht. Das Problem Sie haben es, dass Brightness ist Mitglied Material, jedoch ist Red Mitglied Color und nicht Material, an den Compiler. Mit float* sollte Ihr Problem lösen.

Es ist nicht möglich. Aber es gibt eine Abhilfe ganz in der Nähe zu dem, was Sie erreichen wollen. Es geht um Putting das verschachtelte Mitglied in einer Vereinigung zusammen mit einem „Layout-kompatibel“ anonymous Struktur. Der Nachteil ist ein bisschen aufgebläht Schnittstelle und die Notwendigkeit von Definitionen von Geschwister structs synchron zu halten.

struct Color {
    float Red;
    float Green;
    float Blue; };

struct Material {
    float Brightness;
    union {
        struct { // "Layout-compatible" with 'Color' (see citation below)
            float DiffuseColorRed;
            float DiffuseColorGreen;
            float DiffuseColorBlue; };
        Color DiffuseColor; }; };

int main() {
    Material M;

    float Material::* ParamToAnimate;
    ParamToAnimate = &Material::DiffuseColorRed;
    std::cin >> M.*ParamToAnimate;
    std::cout << M.DiffuseColor.Red << std::endl;
    return 0; }

ISO IEC 14882-2003 (c ++ 03):

  

§3.9

     

11

     

Wenn zwei Typen T1 und T2 vom gleichen Typ ist, dann T1 und T2   Layout-kompatible Typen. [Hinweis: Layout-kompatibel Aufzählungen sind   in 7.2 beschrieben. Layout-kompatibel POD-Strukturen und POD-Gewerkschaften   in 9.2 beschrieben. ]

     

§9.2

     

16

     

Wenn ein POD-Union enthält zwei oder mehr POD-Strukturen, die eine gemeinsame teilen   Anfangssequenz, und wenn das POD-Union Objekt enthält derzeit eine   dieser POD-structs, ist es erlaubt, den gemeinsamen Anfang zu inspizieren   Teil eines von ihnen. Zwei POD-structs eine gemeinsame Anfangssequenz   wenn entsprechende Elemente haben Layout-kompatible Typen (und für   Bitfelder, die gleiche Breite) für eine Folge von einer oder mehreren Anfängen   Mitglieder.

Mehrere Verschachtelung möglich ist, auch:

struct Color {
    float Red;
    float Green;
    float Blue; };

struct Material {
    float Brightness;
    Color DiffuseColor; };

struct Wall {
    union {
        struct {
            float SurfaceBrightness;
            struct {
                float SurfaceDiffuseColorRed;
                float SurfaceDiffuseColorGreen;
                float SurfaceDiffuseColorBlue; }; };
        Material Surface; }; };

int main() {
    Wall W;

    float Wall::* ParamToAnimate;
    ParamToAnimate = &Wall::SurfaceDiffuseColorRed;
    std::cin >> W.*ParamToAnimate;
    std::cout << W.Surface.DiffuseColor.Red << std::endl;
    return 0; }
  

§9.2

     

14

     

Zwei POD-Struktur (Ziffer 9) Typen sind Layout-kompatibel, wenn sie die haben   dieselbe Anzahl von nicht-statischen Datenelemente und entsprechende nicht-statische   Datenelemente (in der Reihenfolge) haben Layout-kompatible Typen (3.9).

Sie könnten einfach so umgestalten, dass Sie nicht über die verschachtelte Struktur überhaupt. Fügen Sie einen Setter als entpackt die Farbe in seine Bestandteile, so dass bestehende Code muss nicht viel ändern, und gehen von dort aus.

Sie können auch einen optionalen zweiten Zeiger nehmen, die in den verschachtelten Typ gräbt. Ein einzelner Test, um zu sehen, wenn Sie den zweiten Parameter müssen gut genug beweisen kann Ihre aktuelle Methode im Vergleich zu, und würde leicht erweitert sollten zusätzliche Felder später wieder auftauchen.

Nehmen Sie das noch einen Schritt weiter, und Sie haben eine Basis MaterialPointer Klasse mit einem virtuellen Dereference Methode. Die Fallklasse können einfache Mitglieder handhaben, mit abgeleiteten Klassen verschachtelte Elemente mit dem, was sie zusätzliche Informationen benötigen Umgang mit ihnen zu finden. Eine Fabrik kann dann MaterialMember* produzieren Objekte des entsprechenden Typs. Natürlich, jetzt bist du mit Heapzuweisungen stecken, so ist dies wahrscheinlich ein wenig zu weit, praktisch zu sein.

Da an einem gewissen Punkt müssen Sie einen Zeiger auf die tatsächlichen Daten, dies kann oder auch nicht für Sie arbeiten:

float Material::* ParamToAnimate;
ParamToAnimate = &Material::Brightness;       // Ok
float Color::* Param2;
Param2 = &Color::Red; 

Material mat;
mat.Brightness = 1.23f;
mat.DiffuseColor.Blue = 1.0f;
mat.DiffuseColor.Green = 2.0f;
mat.DiffuseColor.Red = 3.0f;

float f = mat.DiffuseColor.*Param2;

Wie wäre es Vererbung statt Zusammensetzung?

struct Color {
    float Red;
    float Green;
    float Blue; };

struct DiffuseColor : public Color {
    };

struct Material : public DiffuseColor {
    float Brightness; };


int main() {
    float Material::* ParamToAnimate;
    ParamToAnimate = &Material::Brightness;       // Ok
    ParamToAnimate = &Material::DiffuseColor::Red; // Ok! *whew*
    return 0; }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top