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

时间:2011-02-13 14:11:23

标签: c++ c++-faq

从其他C派生语言(如Java或C#)到C ++,最初很困惑的是C ++有三种方式来引用类的成员:a::ba.b,和a->b。我什么时候使用这些运营商中的哪一个?

<子> (注意:这是Stack Overflow's C++ FAQ的一个条目。如果您想批评在此表单中提供常见问题解答的想法,那么the posting on meta that started all this就是这样做的地方。在C++ chatroom中监控了这个问题,首先是FAQ的想法,所以你的答案很可能会被那些提出想法的人阅读。)

4 个答案:

答案 0 :(得分:231)

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

  1. a::b仅在b是类(或命名空间)a的成员时使用。也就是说,在这种情况下,a将始终是类(或命名空间)的名称。

  2. a.b仅在b是对象(或对象的引用)a的成员时使用。因此对于a.ba将始终是类的实际对象(或对象的引用)。

  3. a->b最初是(*a).b的简写符号。但是,->是唯一可以重载的成员访问运算符,因此如果a是重载operator->的类的对象(常见的类型是智能指针和迭代器)那么意义就是类设计师所实现的。总结:使用a->b,如果a是指针,b将成为指针a引用的对象的成员。但是,如果a是重载此运算符的类的对象,则会调用重载的运算符函数operator->()


  4. 小字:

    • 在C ++中,声明为classstructunion的类型被视为“类类型”。所以上面提到了所有这三个。
    • 引用在语义上是对象的别名,所以我应该在#3中添加“或引用指针”。但是,我认为这会更有说服力,因为很少使用对指针(T*&)的引用。
    • 点和箭头运算符可用于引用对象中的静态类成员,即使它们不是对象的成员。 (感谢Oli指出这一点!)

答案 1 :(得分:33)

建议替代sbi的第3点

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

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

答案 2 :(得分:1)

直接成员选择方案中使用点运算符。

High

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


箭头运算符用于间接成员选择方案中。

b

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


与命名空间相关的直接成员选择方案中使用双冒号(范围)运算符。

a

在这里,我们正在访问b,它是类/命名空间print(a::b) 的成员。因此,b是一个类/命名空间,而a是一个a的成员(函数/变量等)。

答案 3 :(得分:-1)

#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)从指向对象的指针(或由->创建的对象)访问成员(属性和函数)
*使用双冒号(::)从类本身访问静态成员函数,而无需将对象作为句柄。 [注意:,您还可以从.->的实例中调用静态成员函数,不推荐使用]