2010-07-04 16 views
8

¿Cómo fuerzo la const-ness de la memoria apuntada por obj-> val1 en la función fn?C/C++: Punteros dentro de Const Struct

#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; 
} 

El código aquí es bastante autoexplicativo. Necesito poder hacer un objeto no const y llenarlo con datos, pero luego pasarlo a una función donde estos datos no se pueden modificar. ¿Cómo puedo hacer esto?

Sé que puedo pasar un puntero const int, pero teóricamente, esta clase contiene varios otros punteros que necesitaré en "fn" también.

Gracias,

Griff

Respuesta

6

Ya que en la categoría C++, que podrían hacer que el miembro de private y crea un descriptor de acceso que devuelve un const int *. Originalmente puede establecer el miembro a través de su constructor o una función friend.

+0

Ahh. Olvidé que las estructuras en C++ pueden tener métodos y variables miembro. Eso resolverá mi problema, aunque solo para risas, ¿es posible hacer esto en C? – Griffin

+0

@Griffin: si realmente desea asegurarse de que probablemente lo pase por separado. –

+0

@Griffin: sí. Vea mi respuesta, que es válida tanto para C como para C++. –

2

Realmente no se puede. Un const foo especifica que los miembros internos son const, es decir, son punteros constantes para enteros, no punteros a enteros constantes.

La solución adecuada para esto sería a través de la encapsulación, ocultando estos miembros y proporcionando una interfaz pública. Una solución práctica, que debe ser prohibido modificar el struct foo, sería a través de la herencia privada:

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; } 
}; 

Por supuesto, lo que se necesita para crear los constructores apropiados, etc., por lo que el foo original se puede ajustar arriba.

+0

Parece que tendré que añadir algo de complejidad extra a mi pequeña y pobre estructura. Gracias por la muestra del código informativo! – Griffin

4

No soy una persona de C++, pero en C, me encargo de esto a través de dos declaraciones struct diferentes, uno públicas, una privada:

#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; 
} 

Cuando intento compilar lo anterior w/GCC , Obtengo los siguientes errores de compilación, ya que estoy tratando de modificar la memoria de solo lectura:

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 .. Ahora que es inteligente. Felicitaciones a usted, señor. Estoy agregando esto a mi bolsa de trucos. – Griffin

Cuestiones relacionadas