静态成员函数和访问运算符

Posted

技术标签:

【中文标题】静态成员函数和访问运算符【英文标题】:Static member function and access operator 【发布时间】:2019-12-12 12:58:09 【问题描述】:

我只是从 cppreference.com 浏览左值(值类别),发现member access operator 指定为:

在 E1.E2 类型的内置访问运算符中:

3) 如果 E2 是静态成员函数,则结果是指定该静态成员函数的左值。本质上,在这种情况下,E1 被评估并丢弃;

对于非静态成员函数:

4) 如果 E2 是包含析构函数的非静态成员函数,则结果是一种特殊类型的纯右值,指定 E1 的非静态成员函数只能用作成员函数的左操作数呼叫接线员,不得用于其他目的;

我不知道这意味着什么,尤其是第 3 点)如何用作左值以及用于什么目的。 我知道这是一些很少有人使用的详细内容。但出于好奇,任何对任何示例的帮助都将不胜感激::

【问题讨论】:

【参考方案1】:

这是来自 cppreference 的简化示例

#include <iostream>
struct A

    int f()  return 10; 
    static int sf()  return 4; 
;

int main()

    A a;
    std::cout << a.f() << a.sf(); // A::sf() also works

现在,您引用的部分指出 a.sf 是左值,而 a.f 不是。这意味着什么?表示可以取a.sf的地址:

auto fun = &(a.sf); 
fun();

a.f 则不然:

auto fun = &(a.f);   // error 
// ISO C++ forbids taking the address of a bound member function to form a pointer to member function.  Say '&A::f'

【讨论】:

这并不能解释对静态成员函数的调用如何作为 cppreference 中引用的左值工作...... @Tilak_Chad 所以你的问题是关于“......是一个左值......”。我想现在我明白了这个问题;) 我想你想通过*fun() 打电话给fun @n314159 afaik 都很好【参考方案2】:

考虑:

struct X
    static void foo()

    void bar()
;

X makeX()
  std::cout<<"make X called"<<std::endl;
  return X();


int main()
  makeX().foo();
  makeX().bar();

在对makeX().foo()的调用中,foo是一个static成员函数,所以makeX()对应于E1在情况3):它因此被评估和丢弃,所以makeX()被调用,但随后临时的 X 对象被丢弃,foo 被调用,就像您输入了 X::foo() 一样。

在对makeX().bar()的调用中,bar是一个非static的成员函数,所以makeX()被求值,临时的X对象被用作调用的this参数bar.

【讨论】:

【参考方案3】:

例如,您可以获取静态成员函数的地址并将其存储在普通函数指针中(因此不是成员函数指针):

struct X 
    static void f(int);
    void g(int);
;

int main() 
    X x;
    void (*p)(int);
    p = &x.f; // works
    p = &x.g; // does not work

这也是有道理的,因为您可以(仅)调用f 而无需提供X 类型的对象,而您只能在提供此类对象时调用g。由于您希望能够通过*p(0) 调用函数指针,因此您不能允许将&amp;g 分配给p,而&amp;f 没有问题。

您可以将公共静态成员函数大致视为可通过结构/类访问的免费友元函数(不完全是,但它比非静态成员函数更接近)。

【讨论】:

以上是关于静态成员函数和访问运算符的主要内容,如果未能解决你的问题,请参考以下文章

静态成员

类静态成员变量和静态成员函数的访问方式

C++面向对象:静态成员和静态成员函数

关于类中静态成员函数和静态成员变量的知识点

静态成员

C++ 「静态数据成员」和「静态成员函数」的简单认识