Última actualización:2026-10-12
C++ Punteros a miembros e información de tipos¶
::*: seguramente el 99 % de la gente no lo ha usado nunca, ni siquiera lo ha visto; ¡escríbelo en los comentarios si es tu caso! Esta sección explica la sintaxis desde cero y la pone en práctica con un ejemplo real de un proyecto.
1.Qué es ::*¶
C::* es la sintaxis de los punteros a miembros en C++; representa un puntero a un miembro de la clase C. Esta sintaxis sirve para apuntar a variables miembro o funciones miembro de una clase. A diferencia de un puntero normal, un puntero a miembro no apunta a una dirección de memoria concreta de un objeto, sino a la posición del miembro dentro de la clase, y debe usarse junto con una instancia del objeto de esa clase.
1.1 Sintaxis¶
T C::*es un puntero a una variable miembro de tipoTde la claseC.R (C::*)(Args...)es un puntero a una función miembro de la claseCcuyo tipo de retorno esRy cuya lista de parámetros esArgs....
1.2 Puntero a variable miembro¶
Un puntero a variable miembro apunta a una variable miembro de una clase y se escribe con la forma T C::*.
Por ejemplo: en el ejemplo siguiente se define un puntero a miembro ptr que apunta al miembro x de la clase MyClass. obj.*ptr accede a la variable miembro del objeto a través del puntero a miembro.
struct MyClass {
int x;
double y;
};
int MyClass::*ptr = &MyClass::x;
MyClass obj;
obj.x = 10;
std::cout << "obj.x = " << obj.*ptr << std::endl;
1.3 Puntero a función miembro¶
Un puntero a función miembro apunta a una función miembro de una clase y se escribe con la forma R (C::*)(Args...).
Ejemplo: se llama a la función miembro mediante obj.*funcPtr().
3.¿Para qué sirve?¶
Supón que tienes un framework ORM y necesitas obtener el tipo del campo a partir de un puntero a miembro para generar el tipo de la columna correspondiente; puedes escribirlo así:
struct User {
std::string username;
int user_id;
};
// 自动生成数据库列的定义
template <typename T, typename C>
void generate_sql_column(T C::*member_ptr, const std::string& column_name) {
if constexpr (std::is_same_v<T, std::string>) {
std::cout << column_name << " VARCHAR(255)" << std::endl;
} else if constexpr (std::is_integral_v<T>) {
std::cout << column_name << " INT" << std::endl;
}
}
int main() {
// 假设我们想自动为 User 类生成 SQL 表结构
generate_sql_column(&User::username, "username");
generate_sql_column(&User::user_id, "user_id");
return 0;
}
4.¡Utilidades prácticas derivadas de proyectos reales!¶
En proyectos reales podemos usar C::* para extraer el tipo del objeto y del miembro; ¿cómo se implementa?
La respuesta es: plantillas + C::*
En el ejemplo siguiente, mediante value_type_from_member_pointer y class_type_from_member_pointer podemos extraer el tipo del miembro y el de la clase correspondientes; una herramienta muy práctica.
template <typename T, typename C>
struct from_member_pointer_helper<T C::*> {
using value_type = T;
using class_type = C;
};
template <auto Ptr>
struct from_member_pointer : from_member_pointer_helper<typename std::remove_cvref_t<decltype(Ptr)>> {};
template <auto Ptr>
using value_type_from_member_pointer = from_member_pointer<Ptr>::value_type;
template <auto Ptr>
using class_type_from_member_pointer = from_member_pointer<Ptr>::class_type;
Temas relacionados¶
- C++ Evitar el constructor por defecto | C++那些事
- C++ Idioma de la lista de inicialización de clases | C++那些事
- C++: plantillas de clase antes que plantillas de función | C++那些事
- C++ Idioma copy-and-swap | C++那些事
- C++ Inyección de dependencias | C++那些事
- C++ enum class enumeraciones fuertemente tipadas | C++那些事
- C++ Header-Only frente a separación de implementación | C++那些事
- C++ Idioma de evaluación perezosa | C++那些事
- C++ Idioma de la tabla de consulta | C++那些事
- C++ Idioma mixin | C++那些事