2010-07-04 15 views
8

Wie erzwinge ich die Konstanz des Speichers, auf den obj-> val1 in der Funktion fn zeigt?C/C++: Zeiger innerhalb des Konst-Struktes

#include <iostream> 

struct foo { 
    int* val1; 
    int* val2; 
    int* val3; 
}; 

void fn(const foo* obj) 
{ 
    // I don't want to be able to change the integer that val1 points to 
    //obj->val1 = new int[20]; // I can't change the pointer, 
    *(obj->val1) = 20; // But I can change the memory it points to... 
} 

int main(int argc, char* argv[]) 
{ 
    // I need to be able to set foo and pass its value in as const into a function 
    foo stoben; 
    stoben.val1 = new int; 
    *(stoben.val1) = 0; 
    std::cout << *(stoben.val1) << std::endl; // Output is "0" 
    fn(&stoben); 
    std::cout << *(stoben.val1) << std::endl; // Output is "20" 
    delete stoben.val1; 
    return 0; 
} 

Der Code hier ist ziemlich selbst erklärend. Ich muss in der Lage sein, ein nicht-konstantes Objekt zu machen und es mit Daten zu füllen, aber es dann an eine Funktion weiterzugeben, wo diese Daten nicht geändert werden können. Wie kann ich das tun?

Ich weiß, ich kann nur einen const int-Zeiger übergeben, aber theoretisch enthält diese Klasse mehrere andere Zeiger, die ich auch in "fn" brauche.

Danke,

Griff

Antwort

6

Da Sie als C++ markiert, können Sie das Mitglied private machen und einen Accessor machen, dass ein const int * zurückgibt. Sie könnten das Mitglied ursprünglich über Ihren Konstruktor oder eine friend-Funktion festlegen.

+0

Ahh. Ich vergesse, dass Strukturen in C++ Methoden und Membervariablen haben können. Das wird mein Problem lösen, aber nur für das Gekicher, ist es überhaupt möglich, das in C zu machen? – Griffin

+0

@Griffin: Wenn Sie wirklich sicherstellen wollten, dass Sie es wahrscheinlich separat übergeben würden. –

+0

@Griffin: ja. Siehe meine Antwort, die sowohl für C als auch für C++ gültig ist. –

2

Sie können wirklich nicht. Ein const foo gibt an, dass die Member innerhalb const sind, dh sie sind konstante Zeiger auf ganze Zahlen, keine Zeiger auf konstante ganze Zahlen.

Die geeignete Lösung hierfür wäre die Kapselung, das Ausblenden dieser Elemente und das Bereitstellen einer öffentlichen Schnittstelle. Eine praktische Lösung, sollten Sie die Struktur foo zu ändern verboten werden, durch private Erbschaft wäre:

struct foo { 
    int* val1; 
    int* val2; 
    int* val3; 
}; 

struct constFoo : private foo { 
public: 
    const int* getVal1() { return val1; } 
    const int* getVal2() { return val2; } 
    const int* getVal3() { return val3; } 
}; 

Natürlich müßten Sie die entsprechenden Konstrukteure erstellen, etc., so dass die ursprünglich foo eingestellt werden können oben.

+0

Scheint, dass ich meiner armen kleinen Struktur einige zusätzliche Komplexität hinzufügen muss. Danke für das aussagekräftige Codebeispiel! – Griffin

4

Ich bin kein C++ Person, aber in C, würde ich dies durch zwei verschiedene struct Erklärungen behandeln, eine öffentliche, eine private:

#include <stdio.h> 
#include <stdlib.h> 

struct private_foo { 
    int* val1; 
    int* val2; 
    int* val3; 
}; 

struct public_foo { 
    int const * const val1; 
    int const * const val2; 
    int const * const val3; 
}; 


void fn(struct public_foo * obj) 
{ 
    int local; 
    *(obj->val1) = 20; // compile error 
    obj->val1 = &local; // compile error 
} 

int main(int argc, char* argv[]) 
{ 
    // I need to be able to set foo and pass its value in as const into a function 
    struct private_foo stoben; 
    stoben.val1 = malloc(sizeof(int)); 
    if (!stoben.val1) { return -1; } 
    *(stoben.val1) = 0; 
    printf("%d", *(stoben.val1)); 
    fn((struct public_foo *) &stoben); 
    printf("%d", *(stoben.val1)); 
    free(stoben.val1); 
    return 0; 
} 

Wenn ich versuche, die oben w/GCC zu kompilieren , Bekomme ich die folgenden Compilerfehler, da ich versuche, schreibgeschützten Speicher zu ändern:

temp.c: In function ‘fn’: 
temp.c:20: error: assignment of read-only location 
temp.c:21: error: assignment of read-only member ‘val1’ 
+0

Oooo .. Nun, das ist schlau. Ein großes Dankeschön an Sie, mein Herr. Ich füge das zu meiner Trickkiste hinzu. – Griffin