2010-07-23 23 views
10

Por qué no puedo hacer esto:puntero constante asignar a un puntero

char* p = new char[10]; 

void SetString(char * const str) 
{ 
    p = str; 
} 


SetString("Hello"); 

Tengo un puntero constante a un char, ¿por qué no puedo asignar el puntero constante a otro puntero?

Parece ilógico, ya que al asignarlo a otro puntero, no está violando esencialmente la const-ness del puntero de char. ¿O eres tu?

EDIT: Cuando compilo este que dice "error C2440: '=': no ​​se puede convertir de 'char * const * __ W64' a 'char *'"

(estoy tratando de entender un concepto . de un libro que estoy leyendo simplemente no puede obtener el código para compilar

cÓDIGO:.

int _tmain(int argc, _TCHAR* argv[]) 
{ 

    MyString *strg = new MyString(10); 
    strg->SetString("Hello, "); 

    MyString *secondstr = new MyString(7); 
    secondstr->SetString("Tony"); 

    strg->concat(*secondstr, *strg); 

} 

CPP ARCHIVO:

#include "MyStringClass.h" 
#include <string.h> 
#include "stdafx.h" 

#include "MyStringClass.h" 

void MyString::concat(MyString& a, MyString& b) 
{ 
    len = a.len + b.len; 
    s = new char[len + 1]; 
    strcpy(s, a.s); 
    strcat(s, b.s); 
    delete [] s; 

} 

void MyString::SetString(char * const str) 
{ 
    s = str; 
} 

MyString::MyString(int n) 
{ 
    s = new char[n+1]; 
    s[n+1] = '\0'; 
    len = n; 
} 

encabezado del archivo:

#include <string.h> 
#include <stdio.h> 

class MyString 
{ 
private: 
    char* s; 
    int len; 
public: 
    MyString(int n = 80); 

    void SetString (char * const str); 

    void concat (MyString& a, MyString& b); 
}; 
+2

No hay nada de malo en ese código, per se. ¿Por qué no mostrarnos código real con errores de compilación reales para resolver un problema real? – GManNickG

+0

En respuesta a la edición, ¿qué es "compilar esto" ... no ha publicado código compilable. :) Danos un pequeño fragmento de lo que estás compilando, exactamente. – GManNickG

+3

Oh mi. Este código infringe dos principios básicos de programación en C++ para cada línea. No sabría por dónde empezar a decirte lo que está mal con eso. ¿De qué libro estás aprendiendo C++? Sea lo que sea, búrbalo y eche un vistazo a [La guía y la lista definitiva de C++ Book] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) antes de escribir cualquier otra línea – sbi

Respuesta

12

Hay diferencia entre puntero constante y puntero a constante. apuntador constante es un puntero (un número - dirección de memoria) que no puede ser cambiado - que siempre apuntan al mismo objeto determinado a través de la inicialización:

int * const const_pointer = &some_int_var; // will be always pointing to this var 
const_pointer = &some_other_var; // illegal - cannot change the pointer 
*const_pointer = 2; // legal, the pointer is a pointer to non-const 

puntero a constante es un puntero cuyo valor en punta no puede ser cambiado:

const int * pointer_to_const = &some_int_var; // doesn't have to be always pointing to this var 
pointer = &some_other_var; // legal, it's not a constant pointer and we can change it 
*pointer = 2; // illegal, pointed value cannot be changed 

Siempre se puede asignar constante a la variable, es decir, const pointer al puntero no const (a). Puede convertir el puntero a no const a un puntero a const (b). Pero no se puede convertir puntero a const a un puntero a no constante (c):

int * pointer; 
int * const const_pointer = &var; 
const int * pointer_to_const; 

/* a */ 
pointer = const_pointer; // OK, no cast (same type) 

/* b */ 
pointer_to_const = pointer; // OK, casting 'int*' to 'const int*' 

/* c */ 
pointer = pointer_to_const; // Illegal, casting 'const int*' to 'int*' 

[EDIT] A continuación, esto no es C++ estándar. Sin embargo, esto es común [/ EDIT]
cadena literal

"Hello" 

se convierte en puntero constante a const (const char * const):.

char *pointer = "Hello"; // Illegal, cannot cast 'const char*' to 'char*' 
char * const const_pointer = "Hello"; // Illegal, cannot cast 'const char*' to 'char*' 
const char * pointer_to_const = "Hello"; // OK, we can assign a constant to a variable of the same type (and the type is 'const char*') 
"Hello" = pointer_to_const; // Illegal cannot re-assign a constant 

En ejemplos anteriores la segunda es su caso. Intentó inicializar puntero-a-no-const con un puntero-a-const al pasar cadena literal como argumento de su función. No importa si estos punteros son constantes o no, es cuestión de a qué apuntan.

Resumen:
1) Si lanzas un puntero de algún tipo a un puntero de otro tipo, no se puede emitir puntero a const a puntero-a-no-const.
2) Si tiene un puntero constante, se aplican las mismas reglas que para otras constantes: puede asignar una constante a una variable pero no puede asignar una variable a una constante (excepto inicializarla).

// EDITAR
Como GMan señaló, el estándar de C++ 98 (§ 4.2/2) permite a emitir implícitamente literales de cadena (que son constantes arrays carbón de leña) a un puntero char no const. Esto se debe a la compatibilidad con versiones anteriores (en el lenguaje C no hay constantes).

Por supuesto, tal conversión puede conducir a errores y los compiladores violarán la regla y mostrarán un error. Sin embargo, GCC en modo de compatibilidad muestra solo una advertencia.

+2

Esto contiene información incorrecta, lo que lleva a resultados incorrectos. Un string literal es un [array of const char's] (http://stackoverflow.com/questions/3303164/why-isnt-if-maya-maya-true-in-c/3303212#3303212), no un 'const char * '(Aunque, dado que es una matriz, puede descomponerse en tal). Si bien es cierto que una matriz de este tipo no se puede convertir implícitamente a 'char *', los literales de cadena tienen esta conversión especial. (Está obsoleto y solo existe para compatibilidad con versiones anteriores). Por lo tanto, los tres ejemplos de código son completamente legales. – GManNickG

+0

Escribí que "se convierte en un puntero", no "es un puntero". Se convierte en un puntero que apunta a la matriz de la que está hablando. Y está equivocado: los literales de cadena no se pueden convertir implícitamente a 'char *'. Tal vez te confundan con la inicialización de array char. – adf88

+1

No, no lo soy. §4.2/2: "Un literal de cadena (2.13.4) que no es un literal de cadena ancha se puede convertir a un valor r de tipo" puntero a char "; un literal de cadena ancha se puede convertir a un valor de r de tipo" puntero " a wchar_t ". En cualquier caso, el resultado es un puntero al primer elemento de la matriz. Esta conversión se considera solo cuando hay un tipo de destino de puntero apropiado explícito, y no cuando hay una necesidad general de convertir de un valor l a un valor de . [Nota: esta conversión está en desuso. Ver el Anexo D.] "Como dije, las tres líneas son legales. (Bueno, tienes cuatro ahora, los primeros 3.) – GManNickG

Cuestiones relacionadas