简体   繁体   English

在这种情况下,::运算符会做什么

[英]What does the :: operator do in this situation

template <int N>
struct Factorial {
  static const int value = N * Factorial<N - 1>::value;
};

// Base case via template specialization:

template <>
struct Factorial<0> {
  static const int value = 1;
};

So I might have figured out that here the role of the '::' operator is to somehow feed/add into the 'value' variable the content of the operation performed earlier (N * Factorial). 所以我可能已经发现,这里'::'运算符的作用是以某种方式将先前执行的操作内容(N * Factorial)提供/添加到'value'变量中。 But can someone explain this in a more thorough manner (I wouldn't mind a full explanation of the '::' operator roles). 但有人可以更彻底地解释这一点(我不介意'::'运算符角色的完整解释)。

Thank you very much! 非常感谢你!

The :: operator is called the scope resolution operator. ::运算符称为范围解析运算符。 It "resolves," or makes clear, the scope in which the right-hand operand, a variable name, is located. 它“解析”或明确了右侧操作数(变量名称)所在的范围。

For example, std::cout makes it clear to the compiler that the identifier cout should be searched for in the namespace std . 例如, std::cout使编译器清楚地知道应该在命名空间std搜索标识符cout In your case, the Factorial<N - 1>::value makes it clear that value is a member of the templated class Factorial<N - 1> . 在您的情况下, Factorial<N - 1>::value表明value是模板化阶段Factorial<N - 1> It's used here because value is a static field of the class. 它在这里使用,因为value是类的static字段。

So I might have figured out that 所以我可能已经弄清楚了

I strongly suggest learning C++ from a book, and learning to use existing reference material, rather than trying to figure out what some code means from first principles. 我强烈建议从一本书中学习 C ++,并学习使用现有的参考资料,而不是试图弄清楚一些代码从第一原理中意味着什么。 You're very likely to make subtle mistakes if you go by educated guesses. 如果你通过有根据的猜测,你很可能犯下微妙的错误。

The expression Factorial<N - 1>::value is a qualified identifier . 表达式Factorial<N - 1>::value限定标识符

Factorial<N - 1> is the name of a class (an instantiation of the Factorial<int> template with a specific value for the single parameter). Factorial<N - 1>是一个类的名称( Factorial<int>模板的实例化,具有单个参数的特定值)。 This class has a data member called value . 该类有一个名为value的数据成员。 Explicit qualification is needed since this particular value isn't otherwise in scope. 需要明确的鉴定,因为这个特定的 value不在其他范围内。 See also qualified name lookup . 另请参见限定名称查找

You can use :: like this for any class member: for example std::string::npos roughly means find the data member called npos in the class called string in the namespace called std . 您可以对任何类成员使用:: like这样:例如std::string::npos粗略意味着在名为std的名称空间中名为string的类中查找名为npos的数据成员

... somehow feed/add into the 'value' variable the content of the operation performed earlier ... ...以某种方式提供/添加到'value'变量中之前执行的操作的内容......

there is no "earlier", this all happens during the same stage of compilation. 没有“早先”,这一切都发生在编译的同一阶段。

For example, I can manually write 例如,我可以手动编写

struct F_0 { static const int value = 1; }
struct F_1 { static const int value = 1 * F_0::value; }
struct F_2 { static const int value = 2 * F_1::value; }
struct F_3 { static const int value = 3 * F_2::value; }

etc. etc. for as many values as I want. 等我想要的数量等等。 The templated version is effectively the same but saves a lot of typing. 模板化版本实际上是相同的,但节省了大量的输入。

Specifically, writing Factorial<3> instantiates the template Factorial<int N> for N=3 , which means we now have a concrete non-template class Factorial<3> equivalent to the F_3 I wrote manually above. 具体来说,编写Factorial<3> 实例化 N=3的模板Factorial<int N> ,这意味着我们现在有一个具体的非模板类Factorial<3>等同于我在上面手动编写的F_3

The definition of this class refers to Factorial<N-1>::value (with N-1 = 2 ), so Factorial<2> gets instantiated too. 该类的定义是指Factorial<N-1>::valueN-1 = 2 ),因此Factorial<2>也会被实例化。 This chain of implicit instantiations continues until we reach the explicitly specialized Factorial<0> (without that, it'd keep trying to instantiate Factorial<-1> , Factorial<-2> , forever until the compiler gave up and failed). 这个隐式实例化链继续,直到我们到达明确专门的Factorial<0> (没有它,它会一直试图实例化Factorial<-1>Factorial<-2> ,直到编译器放弃并失败)。

If you have a class foo with a static member bar , then you can refer to it with the :: notation as foo::bar . 如果你有一个带有静态成员bar的类foo ,那么你可以:: notation作为foo::bar引用它

Here, Factorial<N - 1> is a class, with a static member value . 因此, Factorial<N - 1>是一个具有静态成员value Asides from the template notation, there is no difference. 除了模板符号,没有区别。

struct Factorial template class resolves value from struct Factorial<N - 1> and each time the value is resolves recursively. struct Factorial模板类从struct Factorial<N - 1>解析value ,并且每次递归解析value And at the end the value will be 1 from the following base case : 最后,以下基本情况的value 1

template <>
struct Factorial<0>

the value determine here : value确定在这里:

Factorial<5> f;
std::cout << f.value << std::endl;

So, the output will be : 120 因此,输出将是: 120

static const int value = N * Factorial<N - 1>::value

It means that the value of the member Factorial<N>::value is N multiplied by the value of the member Factorial<N-1>::value . 这意味着成员Factorial<N>::valueN乘以成员Factorial<N-1>::value (Except for Factorial<0>::value , which is specialised to provide a recursive base case ) Factorial<0>::value除外,它专门用于提供递归基本情况

Both Factorial<N> and Factorial<N-1> are classes. Factorial<N>Factorial<N-1>都是类。

:: is the scope resolution operator and tells the compiler that you want to access a member (in this case, a static member) of the class (or namespace) to the left of it. ::是作用域解析运算符,它告诉编译器您要访问其左侧的类(或命名空间)的成员(在本例中为static成员)。

A simpler example: 一个更简单的例子:

class Foo
{
    static int x;
};

int Foo::x = 42;

int main()
{
   int y = Foo::x;  // access the member 'x' in the class 'Foo'
}

or: 要么:

#include <iostream>

int main()
{
   std::cout << "hi!\n";  // access the object 'cout' in the namespace 'std'
}

To make it more clear consider an alternative access to the data member value . 为了更清楚地考虑对数据成员value的替代访问。

#include <iostream>

template <int N>
struct Factorial {
  static const int value = N * Factorial<N - 1>().value;
};

// Base case via template specialization:

template <>
struct Factorial<0> {
  static const int value = 1;
};

int main()
{
    std::cout << Factorial<12>().value << '\n';
}

The program output is 程序输出是

479001600

Here is used the member access expression Factorial<N - 1>().value or Factorial<12>().value . 这里使用了成员访问表达式Factorial<N - 1>().valueFactorial<12>().value

So to specify an access to the data member value (and especially for non-static data members) you create an object of the type Factorial<N - 1> or Factorial<12>. 因此,要指定对数据成员value的访问权限(尤其是对于非静态数据成员),请创建Factorial<N - 1>或Factorial <12>类型的对象。

But static data members do not require an object of the class to be created. 但是静态数据成员不需要创建类的对象。 So it is much simpler and safer to use a class name and the operator :: to specify an access to a static data member. 因此,使用类名和operator ::指定对静态数据成员的访问权限要简单得多,也更安全。

The member access expression Factorial<N - 1>::value specifies that value is a static data member of the class Factorial<N - 1> . 成员访问表达式Factorial<N - 1>::value指定该valueFactorial<N - 1>类的静态数据成员。 Neither object of the class Factorial<N - 1> is required. Factorial<N - 1>类的对象都不是必需的。 It is enough to specify the name of the class to which the static data member belongs. 只需指定静态数据成员所属的类的名称即可。

The '::-operator' is used to access things in namespaces (std::string) or static things in a class: ':: - operator'用于访问命名空间(std :: string)中的内容或类中的静态内容:

struct C {
    static int i = 42;
};
int main() {
    std::cout << C::i << '\n';
}

Here C::i is static, so I don't need an instance of class C. To access some non-static thing inside a class you use a '.'. 这里C :: i是静态的,所以我不需要类C的实例。要访问类中的一些非静态的东西,你使用'。'。 In your example Factorial is no class but a template, Factorial is a class and Factorial::value is the static int value inside the class Factorial. 在你的例子中,Factorial不是类而是模板,Factorial是一个类,Factorial :: value是Factorial类中的静态int值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM