我对一些C ++规则有几个问题。
为什么在包含返回类型时,我能够从命名空间中的类外部调用函数/方法? (查看下面代码中的命名空间test2 :: testclass2),即可以:
bool b = testclass1::foo<int>(2);
虽然这不是: - (它甚至不编译 - 编译器抛出这是函数重新声明)
testclass1::foo<int>(2);
C ++抱怨这是一个功能重新声明。是这样吗?
这一行:
bool b = testclass1::foo<int>(2);
首先在其他任何事情之前先调用。这是因为静态方法总是先在C ++中的其他任何东西之前创建吗?
我在哪里可以找到这些规则?我家里有一些C ++书籍,所以如果有人能够指出一本书(以及章节或页面)或者将我引导到一个网站,我将非常感激。
以下是我在家中使用Visual Studio 2008测试的示例(部分)代码:
class testclass1
{
public:
testclass1(void);
~testclass1(void);
template<class A> static bool foo(int i)
{
std::cout <<"in static foo";
return true;
}
};
namespace test2
{
class testclass2
{
public:
testclass2(void);
~testclass2(void);
};
bool b = testclass1::foo<int>(2);
}
编辑:
有些人提到我需要在函数内部调用它,这将毫无问题地工作 我明白那个;我问这个问题的唯一原因是因为我在某个地方看到了这个代码(在别人的项目中)并且想知道这是如何以及为什么这样做。因为我以前从未见过有人这样做过。
此外,它(在多个地方)用作通过这些函数调用(在外部)调用和实例化大量类的方法。在实例化任何其他内容之前,它们首先被调用。
答案 0 :(得分:4)
C ++不是Python。您在函数中编写语句,并从main
方法开始执行。 bool b = ...
恰好起作用的原因是它定义全局变量b
,而函数调用仅仅是初始化表达式。
定义可以存在于函数外部,而其他语句只能存在于函数体内。
答案 1 :(得分:3)
当我包含返回类型时,为什么我能够从命名空间中的类外部调用函数/方法? (查看命名空间test2 :: testclass2)
b
的声明不在函数内部,因此您声明了一个全局变量。如果你在函数的作用域内,你的第二个语句就可以了,但是在函数之外它是没有意义的。
这也回答了你的第二个问题。
当然,如果它不是静态成员函数,则不允许以这种方式调用它(即不作为对象的方法)。
答案 2 :(得分:0)
您可以在例如Koenig lookup中的standard documentation和模板 - 祝你好好导航!你没有提到你正在测试哪个编译器,但我不完全确定它是否合规!
正如Mehrdad所指出的那样,你在test2命名空间中声明并初始化一个全局变量:这与静态方法无关。
答案 3 :(得分:0)
如果你在下面的函数中写这个,那么它的工作没有问题。如上所述,除非使用函数初始化全局变量,否则需要在函数内调用这些函数...
int main()
{
testclass1::foo<int>(2);
return 0;
}
答案 4 :(得分:0)
1。首先,一个有用的更正:你说“......当我包含返回类型时”。我想你可能会误解<int>
testclass1::foo<int>(2)
部分的作用。它(不一定)指定返回类型,它只为模板参数“A”提供一个值。
您可以选择使用A作为返回类型,但是您将返回类型硬编码为“bool”。
基本上,对于你编写的函数,你总是需要有<>
才能调用它。当从函数参数推断出类型时,C ++允许你省略函数的<args>
;为了做到这一点,你必须在函数参数中使用类型参数A.例如,如果您以这种方式声明函数,那么您可以在没有<>
:
template<class A> static bool foo(A i);
在这种情况下,你可以调用“foo(2)”,它会将A从第二个推断为“int”。
另一方面,没有任何方法可以根据您分配函数的内容推断出任何内容。对于模板参数推导,它只查看函数的参数,而不是调用函数的结果。所以在:
bool b = testclass1::foo(2);
没有办法让它从中推断出“bool”,即使你把A作为返回类型也是如此。
那么为什么编译器不会告诉你“你需要在函数上使用<>
”?即使您将foo声明为模板函数,您也可以使用非模板版本重载它。因此,编译器不会自动假设您在离开<>
电话时尝试调用模板函数。不幸的是,没有假设你正在调用template-foo并且没有看到foo的任何其他声明,编译器然后回退到旧的C样式规则,其中一个函数接受一个int并返回一个int,在一个非常古老的C语言中在使用它之前你不需要声明那种。所以编译器假设这就是你想要的 - 但后来它注意到template-foo和old-crufty-C-foo都采用了int参数,并意识到它无法区分它们之间的区别。所以它说你不能宣布foo。这就是为什么C ++编译器因提供错误的错误消息而臭名昭着的原因 - 当报告错误时,编译器可能完全脱离了轨道并且正在谈论从实际代码中移除三到四级的东西!
2。是的,你是完全正确的。
3. 我发现IBM在线提供的C ++参考和白皮书信息量最大。以下是有关模板的部分的链接:C++ Templates