ChatGPT解决这个技术问题 Extra ChatGPT

何时使用点、箭头或双冒号来引用 C++ 中的类成员?

从其他 C 派生语言(如 Java 或 C#)到 C++,C++ 具有三种引用类成员的方式一开始非常令人困惑:a::ba.ba->b。我什么时候使用这些运算符中的哪一个?

_(注意:这是 [Stack Overflow 的 C++ 常见问题解答](https://stackoverflow.com/questions/tagged/c++-faq) 的一个条目。如果您想批评以这种形式提供常见问题解答的想法,然后[开始这一切的 meta 上的帖子](https://meta.stackexchange.com/questions/68647/setting-up-a-faq-for-the-c-tag)将是这样做的地方. 该问题的答案在 [C++ 聊天室](https://chat.stackoverflow.com/rooms/10/c-lounge) 中进行监控,FAQ 想法最初就是从那里开始的,所以你的答案很可能让提出这个想法的人阅读。)_


d
displayName

C++ 用于访问类或类对象成员的三个不同运算符,即双冒号 ::、点 . 和箭头 ->,用于三种不同的场景,这些场景总是定义明确的.知道这一点后,您只需分别查看您查看的任何代码中的 a::ba.ba->b,即可立即了解很多关于 ab 的信息。

a::b 仅在 b 是类(或命名空间)a 的成员时使用。也就是说,在这种情况下,a 将始终是类(或命名空间)的名称。仅当 b 是对象(或对对象的引用)a 的成员时才使用 ab。因此对于 ab,a 将始终是类的实际对象(或对对象的引用)。 a->b 最初是 (*a).b 的简写符号。但是,-> 是唯一可以重载的成员访问运算符,因此如果 a 是重载 operator-> 的类的对象(常见的此类类型是智能指针和迭代器),那么其含义就是类设计者实施的。总结:对于 a->b,如果 a 是指针,b 将是指针 a 所指对象的成员。但是,如果 a 是重载此运算符的类的对象,则将调用重载的运算符函数 operator->()。

小字:

在 C++ 中,声明为类、结构或联合的类型被视为“类类型”。所以上面提到的都是他们三个。

引用在语义上是对象的别名,所以我也应该在#3 中添加“或对指针的引用”。但是,我认为这会比有用更令人困惑,因为很少使用对指针 (T*&) 的引用。

点和箭头运算符可用于引用对象中的静态类成员,即使它们不是对象的成员。 (感谢奥利指出这一点!)


可能应该澄清的是,.-> 也可以用于通过对象访问类静态,即使它们不是严格的“对象的成员”。
@Oli:确实如此。我已将它添加到小字体中,因为我认为它不常见且不够重要,无法在正文中列出。
为了完整起见,可能值得指出 operator*() 也可以重载,并且没有任何东西强制重载与 operator->() 一致! (顺便说一句,我没有投反对票,只是通过一长串重复来到这里)
@OliCharlesworth 您知道 C++ 标准中指定的位置吗?
@juanchopanza:但是,您无法通过重载 operator* 和使用 . 来获得 -> 的链接行为。只有 operator-> 重载可以做到这一点。
s
sbi

为 sbi 的第 3 点提出替代方案

仅当 a 是指针时才使用 a->b。它是 (*a).b 的简写,a 指向的对象的 b 成员。 C++ 有两种指针,“常规”指针和智能指针。对于 A* a 等常规指针,编译器实现 ->。对于 std::shared_ptr<A> a 等智能指针,-> 是类 shared_ptr 的成员函数。

理由:本常见问题解答的目标受众不是编写智能指针。他们不需要知道 -> 真的称为 operator->(),或者它是唯一可以重载的成员访问方法。


不管我是否同意,我给这个+1只是为了提供一个替代答案。
好吧,公平地说,-> 对于任何 C++ 程序员都应该很快遇到的标准迭代器也是重载的,所以说它仅用于指针可能会令人困惑。
@Kiscsirke“普通 C++ 程序员”不需要编写智能指针或迭代器类型,只需使用它们即可。 “像指针一样取消引用”适用于两者。
m
muditrustagii

点运算符用于直接成员选择场景。

print(a.b)

在这里,我们正在访问 b,它是对象 a 的直接成员。因此,首先,a 是一个对象,而 ba 的成员(函数/变量等)。

箭头运算符用于间接成员选择场景。

print(a->b)

在这里,我们正在访问 b,它是对象的成员,由 a 指向。它是 (*a).b 的简写,因此在这里,a 主要是指向对象的指针,而 b 是该对象的成员。

双冒号(Scope)运算符用于命名空间相关的直接成员选择场景。

print(a::b)

在这里,我们访问的是 b,它是类/命名空间 a 的成员。因此,首先,a 是类/命名空间,ba 的成员(函数/变量等) .


H
Hu Xixi
#include <iostream>
#include <string>

using namespace std;

class Human {
private:
    int age;

public:
    string name;

    Human(int humanAge, string humanName) 
         : age(humanAge), name(std::move(humanName)) {}

    void DoSomething() {
        cout << age << endl;
    }

    static void DisplayAge(const Human& person) {
        cout << person.age << endl;
    }

    // ...
};

int main() {
    // Usage of Dot(.) 
    Human firstMan(13, "Jim"); // firstMan is an instance of class Human
    cout << firstMan.name << endl; // accessing member attributes
    firstMan.DoSomething(); // accessing member functions

    // Usage of Pointer Operator (->)
    Human* secondMan = new Human(24, "Tom");
    cout << secondMan->name << endl; // accessing member attributes
    secondMan->DoSomething(); // accessing member functions
    cout << (*secondMan).name << endl; // accessing member attributes
    (*secondMan).DoSomething(); // accessing member functions

    // Usage of Double Colon (::)
    Human::DisplayAge(firstMan);
    firstMan.DisplayAge(firstMan); // ok but not recommended
    secondMan->DisplayAge(firstMan); // ok but not recommended

    delete(secondMan);

    return 0;
}

从上面的代码示例中,我们看到:
* 使用点运算符 (.) 从实例(或对象)访问成员(属性和函数)
* 从一个实例(或对象)访问成员(属性和函数)使用指针运算符 (->) 指向对象(或由 new 创建)的指针
* 从类本身访问静态成员函数,而无需使用双冒号 (::) 作为句柄的对象。 [注意:您也可以使用 .-> 从实例调用静态成员函数,不推荐使用]


@sbi 好脾气暴躁哈,我知道这是某种重复。我只想给出一个明确的例子来展示如何使用它们。我在哪里说过 -> 只能由 new 在堆上分配的指针使用?下面,第二项,我想我真的很清楚->是指针。在你投反对票之前,你最好自己用 c++14 尝试 className::non_static_member_function()。引用不是指针,所以它可以使用.,我会在我的回答中说得更清楚。