Saltar a contenido

Ú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 tipo T de la clase C.
  • R (C::*)(Args...) es un puntero a una función miembro de la clase C cuyo tipo de retorno es R y cuya lista de parámetros es Args....

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().

void (MyClass::*funcPtr)() const = &MyClass::print;
MyClass obj;
(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

Comentarios