【问题标题】:C++'s double colon used after a class name instead of a namespaceC++ 的双冒号在类名而不是命名空间之后使用
【发布时间】:2019-07-01 12:26:34
【问题描述】:

我正在尝试理解here 列出的 C++ 程序。我对第 86-87 行第二次使用双冒号感到困惑:

 using TransformType = itk::AffineTransform< ScalarType, Dimension >;
 TransformType::Pointer transform = TransformType::New();

看起来TransformType 是一个用户定义的类型。在New() 之前如何使用它?听说双冒号要跟在命名空间后面,但是这里TransformType是一个类型(即类)而不是命名空间。有人可以澄清一下---应该在 C++ 中的命名空间之后始终使用双冒号吗?是否可以使用点(如在 Java 中)?

【问题讨论】:

  • 如果一个类TransformType有一个静态成员函数New(),你可以使用TransformType::New()调用它。 :: 是作用域解析运算符,它不限于命名空间。见:en.cppreference.com/w/cpp/language/qualified_lookup
  • 操作符::scoping操作符,用来表示作用域。所以TransformType::New() 意味着(基本上)“在TransformType 的范围内调用函数New”。
  • @Someprogrammerdude 谢谢。在那种情况下,是否可以像在 Java 中一样使用“TransformType.New()”?我的意思是,使用点而不是两列?
  • 不,因为TransformType 是一个类型名称。您不能将其用作对象实例(因为它不是)。
  • Java 和 C++ 使用不同的语法和语义。它们是外观相似的语言,但非常不同。它们都是优秀、成功的语言,但章程和原则略有不同。

标签: c++ syntax


【解决方案1】:

您使用范围解析运算符 (::) 来命名命名空间、类或范围枚举中的某些内容;这称为qualified lookup

#include <iostream>

namespace N
{
   int x = 0;
}

int main()
{
   std::cout << N::x << '\n';
}

将它与类一起使用通常意味着您指的是某个static 成员,否则您通常会使用objectInstance.member

#include <iostream>

class C
{
public:
   static int x;
}

int C::x = 0;

int main()
{
   std::cout << C::x << '\n';
}

不过,在非静态成员函数中,:: 仍有一些用途,例如消除同时存在于不同基数中的名称。

class Base
{
public:
   void foo() {}
};

class Derived : public Base
{
public:
   void foo()
   {
      // Do base version (omitting Base:: will just call this one again!)
      Base::foo();

      // Now maybe do other things too
   }
};

int main()
{
   Derived obj;
   obj.foo();
}

… 或用于在不需要对象上下文的情况下命名非static 成员:

#include <iostream>

class C
{
public:
   int x;
}

int main()
{
    std::cout << sizeof(C::x) << '\n';

    decltype(C::x) y = 42;
}

作用域枚举需要它,因为它们是作用域的;这就是他们的全部意义所在。它们不会泄漏到周围的范围内,而是有自己的范围,因此您需要具体指定。

enum class E
{
   Alpha,
   Bravo,
   Charlie
};

void foo(E value) {}

int main()
{
   foo(E::Alpha);
}

某些语言允许您使用类型名称后跟. 访问类的static 成员,就像您可以使用对象名称后跟. 访问非static 类成员一样。 C++ 不是其中一种语言。

顺便说一句,这是合法的:

#include <iostream>

class C
{
public:
   int x = 42;
};

int main()
{
   C obj;
   std::cout << obj.C::x << '\n';
//                  ^^^ what?!
}

这里没有必要为x 添加范围解析,因为该语言已经从obj. 知道您正在请求类C 的成员。但如果你愿意,你仍然可以添加它。在这种情况下,它通常只是“为您完成”。

【讨论】:

  • 既然您提到了obj.C::x,您可能还想提及sizeof(C::x)decltype(C::x) 以获得非静态x
猜你喜欢
  • 1970-01-01
  • 2020-04-27
  • 1970-01-01
  • 2023-04-07
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
相关资源
最近更新 更多