何时使用"::",何时使用"."

15
抱歉,我有一个非常基础的问题需要问一下。
我在网上查找时无法了解C ++中运算符::和.之间的区别。
我具有几年C#和Java经验,并熟悉使用.操作符进行成员访问的概念。
请问什么情况下应使用这些操作符以及它们之间的区别是什么?
感谢您的时间。

1
:: 用于访问静态类成员或命名空间符号,. 用于访问实例成员。 - jxh
:: 是作用域运算符。 - Dhruv Gairola
3
别忘了 -> -- 如果你不理解 ::. 的区别,那么 -> 也可能会让你感到困惑。 ;-] - ildjarn
7个回答

27

两者的区别在于第一个是作用域解析运算符,而第二个是成员访问语法。

所以,::(作用域解析)可以用来访问命名空间中更深层次的内容,比如嵌套类或静态函数。而.点操作符则只能访问你正在使用的类实例的任何可见成员。

以下是一些示例:

class A {
    public:

        class B { };

        static void foo() {}
        void bar() {}
};

//Create instance of nested class B.
A::B myB; 

//Call normal function on instance of A.
A a;
a.bar();

//Call the static function on the class (rather than on an instance of the class). 
A::foo(); 
请注意,静态函数或数据成员是属于类本身的,无论您是否创建了该类的任何实例。因此,如果我的类中有一个静态变量,并且创建了一千个该类的实例,仍然只有一个静态变量实例。但对于任何其他非静态成员,每个类的实例都会有一个自己的副本,因此一共会有一千个副本。
另外还有一个有趣的选项,在遇到它时可以考虑一下 :) 您还将看到:
//Create a pointer to a dynamically allocated A.
A* a = new A();

//Invoke/call bar through the pointer.
a->bar();

//Free the memory!!! 
delete a;

如果你还没有学习动态内存,它可能会有点令人困惑,所以我不会详细介绍。只是想让你知道,你可以使用{::.->}访问成员 :)


说得好,我也喜欢包含 -> 运算符。 - McKay
很棒的答案,解决了我需要知道的问题。我已经做了相当多的C语言,所以我习惯于使用->语法,但还是感谢您在答案中包含它! - Jordan
当然,它并没有解释(甚至没有提到).*或->*,但我们可能不想在这个阶段就吓跑OP离开C++。 :) - abarnert
哈哈,是的,我认为那会有点刻薄 :) - John Humphreys

8
在C++中,::是作用域解析运算符。它用于区分名称空间和静态方法,基本上任何没有对象的情况下都可以使用。而.用于访问对象内部的内容。
在C#中,.运算符同时用于这两种情况。
namespace Foo
{
    public class Bar
    {          
        public void Method()
        {
        }

        public static void Instance()
        {
        }

    }
}

在C#中,你会像这样编写代码:
var blah = new Foo.Bar();
blah.Method();

但是相应的C++代码看起来更像这样:
Foo::Bar blah;
blah.Method();

请注意,由于您没有引用对象,因此静态方法也将使用作用域分辨符号进行访问。

Foo::Bar::Instance();

在这里,C#代码只会使用点运算符。

Foo.Bar.Instance();

2
但是,“类内部的东西”也可以指静态成员。这些成员使用::访问。因此,::用于除了区分命名空间之外的其他用途。 - Rob Kennedy
@RobKennedy 我已经修改了答案以涵盖这种情况。 - McKay
@ildjarn 啊,这个怎么样?这个例子更好吗? - McKay
@McKay:确实。;-](请注意,那不是我的负评。) - ildjarn
@ildjarn 是的,我认为这是 Rob 的。它出现在他评论的时间左右。 - McKay
显示剩余3条评论

4

:: 用于命名空间和静态成员访问,而C#则使用点运算符来表示命名空间。

. 用于非静态成员访问。

这并不是详尽的区分,但在使用C#和Java时,这些相关部分可能会令您感到困惑。

如需更多信息,请参阅:

IBM - 域解析运算符

IBM - 点运算符


请提供简洁明了的答案,每个正确回答加一分。 - Joe Schrag

2

:: 是作用域解析运算符,所以当你解析命名空间或类的范围时,使用它。对于成员访问,你需要使用 .


1
作用域运算符::如果你不理解命名空间或类,可能会很难理解。 命名空间就像代码中各种事物名称的容器。 它们通常用于消除库中常见名称的歧义。 假设命名空间stdexample都有函数foobar()。 为了让编译器知道你要使用哪个函数,你可以将其前缀设置为std::foobar()example::foobar()
当告诉编译器您要定义在类或结构中声明的函数时,也可以使用::运算符。例如:
class foobar()
{
  public:
  void hello();
  int number; //assume there is a constructor that sets this to 5
}

void foobar::hello()
{
  cout << "Hello, world!" << endl;
}

. 运算符用于访问类或结构体的成员。例如:

foobar foo;
foo.hello();
cout << foo.number << endl;

假设该类通过编写构造函数完成,那么预期的输出将是:
Hello, world!
5

0

在Java中,当在程序中创建类后访问成员时,您可以像使用 .运算符一样使用它。

::则在以下情况下使用:

当您在某个类的.h/.cpp文件中定义方法时,请写:

class::methodName()

不管是用于原型设计还是实现。

另外,如果你没有明确声明使用的命名空间,那么你就必须使用它。

std::cout << "This is the output";

不要只是使用cout << "This is the output;

也许还有更多,但我现在记不清了,我的C++有点生疏。


0
在C++中,::用于标识作用域。这可以是命名空间作用域 或者 类作用域
例如:
int x;

namespace N {
    int x;

    struct foo {
        static double x;
        double y;    
    };
    struct bar: public foo {
        double y;
    };
}

int main()
{
    int x; // we have a local, hiding the global name
    x = ::x; // explicitly identify the x in global scope
    x += N::x; // explicitly identify the x in namespace N

    N::foo::x = x; // set the static member of foo to our local integer
    N::foo f;
    f.y = f.x; // the static member is implicitly scoped by the object
    f.y += N::foo::x; // or explicitly scoped

    N::bar b;
    assert(b.x == N::foo::x); // this static member is inherited
    b.y = b.x; // we get N::bar::y by default
    b.N::foo::y = b.y; // explicitly request the hidden inherited one
}

// we need to define the storage for that static somewhere too ...
int N::foo::x (0.0);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接