:: 运算符在这种情况下做什么
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;
};
所以我可能已经弄清楚这里 '::' 运算符的作用是以某种方式 feed/add 进入 'value' 变量之前执行的操作内容 (N * Factorial) .但是有人可以更彻底地解释一下吗(我不介意对“::”运算符角色的完整解释)。
非常感谢!
struct Factorial
模板 class 从 struct Factorial<N - 1>
解析 value
并且每次递归解析 value
。最后 value
将是 1
来自以下基本情况:
template <>
struct Factorial<0>
这里value
确定:
Factorial<5> f;
std::cout << f.value << std::endl;
因此,输出将是:120
如果您有一个 class foo
和一个静态成员 bar
,那么您可以 refer to it with the ::
notation 为 foo::bar
。
这里,Factorial<N - 1>
是一个class,有一个静态成员value
。除了模板符号外,没有区别。
::
运算符称为作用域解析运算符。它 "resolves," 或明确表示 right-hand 操作数(变量名)所在的范围。
例如,std::cout
向编译器明确表示应该在命名空间 std
中搜索标识符 cout
。在你的例子中,Factorial<N - 1>::value
清楚地表明 value
是模板化 class Factorial<N - 1>
的成员。此处使用它是因为 value
是 class.
的 static
字段
static const int value = N * Factorial<N - 1>::value
表示成员Factorial<N>::value
的值是N
乘以成员Factorial<N-1>::value
的值。 (Factorial<0>::value
除外,它专门提供递归基本情况)
Factorial<N>
和Factorial<N-1>
都是class。
::
是范围解析运算符,它告诉编译器您要访问 class(或命名空间)的成员(在本例中为 static
成员)在它的左边。
一个更简单的例子:
class Foo
{
static int x;
};
int Foo::x = 42;
int main()
{
int y = Foo::x; // access the member 'x' in the class 'Foo'
}
或:
#include <iostream>
int main()
{
std::cout << "hi!\n"; // access the object 'cout' in the namespace 'std'
}
So I might have figured out that
我强烈建议从书中学习 C++,并学习使用现有的参考资料material,而不是试图从基本原理中弄清楚一些代码的含义。如果您进行有根据的猜测,您很可能会犯一些细微的错误。
表达式 Factorial<N - 1>::value
是 qualified identifier.
Factorial<N - 1>
是 class 的名称(Factorial<int>
模板的实例,具有单个参数的特定值)。这个 class 有一个名为 value
的数据成员。需要明确限定,因为此 particular value
不在范围内。另见 qualified name lookup.
您可以像这样对任何 class 成员使用 ::
:例如 std::string::npos
大致意味着 在class 在名为 std
.
的命名空间中调用了 string
... somehow feed/add into the 'value' variable the content of the operation performed earlier ...
没有"earlier",这一切都发生在编译的同一阶段。
比如我可以手动写
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; }
等等我想要的尽可能多的值。模板化版本实际上是相同的,但节省了很多输入。
具体来说,编写 Factorial<3>
实例化 模板 Factorial<int N>
用于 N=3
,这意味着我们现在有一个具体的 non-template class Factorial<3>
相当于我上面手动写的F_3
这个class的定义引用了Factorial<N-1>::value
(N-1 = 2
),所以Factorial<2>
也被实例化了。这个隐式实例化链一直持续到我们到达显式特化的 Factorial<0>
(否则,它会一直尝试实例化 Factorial<-1>
、Factorial<-2>
,直到编译器放弃并失败)。
'::-operator' 用于访问命名空间 (std::string) 中的内容或 class:
中的静态内容
struct C {
static int i = 42;
};
int main() {
std::cout << C::i << '\n';
}
此处 C::i 是静态的,所以我不需要 class C 的实例。要访问 class 中的某些 non-static 内容,您可以使用 ' .'。在您的示例中,Factorial 不是 class 而是一个模板,Factorial 是 class 并且 Factorial::value 是 class Factorial.
中的静态 int 值
为了更清楚地考虑对数据成员的替代访问 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';
}
程序输出为
479001600
这里使用成员访问表达式Factorial<N - 1>().value
或Factorial<12>().value
.
因此,要指定对数据成员 value
(尤其是 non-static 数据成员)的访问权限,您可以创建类型为 Factorial<N - 1>
或 Factorial<12> 的对象。
但是静态数据成员不需要创建 class 的对象。因此,使用 class 名称和运算符 :: 来指定对静态数据成员的访问要简单和安全得多。
成员访问表达式 Factorial<N - 1>::value
指定 value
是 class Factorial<N - 1>
的静态数据成员。 class Factorial<N - 1>
的两个对象都不是必需的。指定静态数据成员所属的 class 的名称就足够了。
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;
};
所以我可能已经弄清楚这里 '::' 运算符的作用是以某种方式 feed/add 进入 'value' 变量之前执行的操作内容 (N * Factorial) .但是有人可以更彻底地解释一下吗(我不介意对“::”运算符角色的完整解释)。
非常感谢!
struct Factorial
模板 class 从 struct Factorial<N - 1>
解析 value
并且每次递归解析 value
。最后 value
将是 1
来自以下基本情况:
template <>
struct Factorial<0>
这里value
确定:
Factorial<5> f;
std::cout << f.value << std::endl;
因此,输出将是:120
如果您有一个 class foo
和一个静态成员 bar
,那么您可以 refer to it with the ::
notation 为 foo::bar
。
这里,Factorial<N - 1>
是一个class,有一个静态成员value
。除了模板符号外,没有区别。
::
运算符称为作用域解析运算符。它 "resolves," 或明确表示 right-hand 操作数(变量名)所在的范围。
例如,std::cout
向编译器明确表示应该在命名空间 std
中搜索标识符 cout
。在你的例子中,Factorial<N - 1>::value
清楚地表明 value
是模板化 class Factorial<N - 1>
的成员。此处使用它是因为 value
是 class.
static
字段
static const int value = N * Factorial<N - 1>::value
表示成员Factorial<N>::value
的值是N
乘以成员Factorial<N-1>::value
的值。 (Factorial<0>::value
除外,它专门提供递归基本情况)
Factorial<N>
和Factorial<N-1>
都是class。
::
是范围解析运算符,它告诉编译器您要访问 class(或命名空间)的成员(在本例中为 static
成员)在它的左边。
一个更简单的例子:
class Foo
{
static int x;
};
int Foo::x = 42;
int main()
{
int y = Foo::x; // access the member 'x' in the class 'Foo'
}
或:
#include <iostream>
int main()
{
std::cout << "hi!\n"; // access the object 'cout' in the namespace 'std'
}
So I might have figured out that
我强烈建议从书中学习 C++,并学习使用现有的参考资料material,而不是试图从基本原理中弄清楚一些代码的含义。如果您进行有根据的猜测,您很可能会犯一些细微的错误。
表达式 Factorial<N - 1>::value
是 qualified identifier.
Factorial<N - 1>
是 class 的名称(Factorial<int>
模板的实例,具有单个参数的特定值)。这个 class 有一个名为 value
的数据成员。需要明确限定,因为此 particular value
不在范围内。另见 qualified name lookup.
您可以像这样对任何 class 成员使用 ::
:例如 std::string::npos
大致意味着 在class 在名为 std
.
string
... somehow feed/add into the 'value' variable the content of the operation performed earlier ...
没有"earlier",这一切都发生在编译的同一阶段。
比如我可以手动写
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; }
等等我想要的尽可能多的值。模板化版本实际上是相同的,但节省了很多输入。
具体来说,编写 Factorial<3>
实例化 模板 Factorial<int N>
用于 N=3
,这意味着我们现在有一个具体的 non-template class Factorial<3>
相当于我上面手动写的F_3
这个class的定义引用了Factorial<N-1>::value
(N-1 = 2
),所以Factorial<2>
也被实例化了。这个隐式实例化链一直持续到我们到达显式特化的 Factorial<0>
(否则,它会一直尝试实例化 Factorial<-1>
、Factorial<-2>
,直到编译器放弃并失败)。
'::-operator' 用于访问命名空间 (std::string) 中的内容或 class:
中的静态内容struct C {
static int i = 42;
};
int main() {
std::cout << C::i << '\n';
}
此处 C::i 是静态的,所以我不需要 class C 的实例。要访问 class 中的某些 non-static 内容,您可以使用 ' .'。在您的示例中,Factorial 不是 class 而是一个模板,Factorial 是 class 并且 Factorial::value 是 class Factorial.
中的静态 int 值为了更清楚地考虑对数据成员的替代访问 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';
}
程序输出为
479001600
这里使用成员访问表达式Factorial<N - 1>().value
或Factorial<12>().value
.
因此,要指定对数据成员 value
(尤其是 non-static 数据成员)的访问权限,您可以创建类型为 Factorial<N - 1>
或 Factorial<12> 的对象。
但是静态数据成员不需要创建 class 的对象。因此,使用 class 名称和运算符 :: 来指定对静态数据成员的访问要简单和安全得多。
成员访问表达式 Factorial<N - 1>::value
指定 value
是 class Factorial<N - 1>
的静态数据成员。 class Factorial<N - 1>
的两个对象都不是必需的。指定静态数据成员所属的 class 的名称就足够了。