这是一个小测试程序:
#include <iostream>
class Test
{
public:
static void DoCrash(){ std::cout<< "TEST IT!"<< std::endl; }
};
int main()
{
Test k;
k.DoCrash(); // calling a static method like a member method...
std::system("pause");
return 0;
}
在VS2008 + SP1(vc9)上编译很好:控制台只显示“TEST IT!”。
据我所知,不应该在instanced对象上调用静态成员方法。
答案 0 :(得分:60)
标准声明没有必要通过实例调用方法,这并不意味着你不能这样做。甚至有一个使用它的例子:
C ++ 03,9.4静态成员
可以使用。来引用类X的静态成员 qualified-id表达式X :: s;它是 没必要使用类成员访问语法(5.2.5)来引用 到静态成员。静态成员 可以 使用类成员访问语法引用,其中 case的表达式是 评价。
class process {
public:
static void reschedule();
};
process& g();
void f()
{
process::reschedule(); // OK: no object necessary
g().reschedule(); // g() is called
}
答案 1 :(得分:11)
静态函数不需要被调用的实例化对象,所以
k.DoCrash();
表现与
完全相同Test::DoCrash();
使用范围解析运算符(::)来确定类中的静态函数。
请注意,在这两种情况下,编译器都不会将this
指针放在堆栈中,因为静态函数不需要它。
答案 2 :(得分:3)
2)如果这是正确的,那为什么?我找不到为什么会被允许,或者可能是为了帮助在模板中使用“静态或非”方法?
它在以下几种情况下可能有用:
[你建议的模板中的“静态或非静态”方法:] 当可以为模板指定了许多类型时,然后模板想要调用该成员:提供静态函数的类型可以使用与成员函数相同的符号来调用 - 前者可能更有效(没有this
指向传递/绑定的指针),而后者允许多态(virtual
)发送和使用会员数据
尽量减少代码维护
如果某个函数从需要特定于实例的数据发展到不需要它 - 并因此使static
允许轻松实例化并防止意外使用实例数据 - 所有现有点客户端使用不需要进行大量更新
如果类型已更改var.f()
调用继续使用var
类型的功能,而Type::f()
可能需要手动更正
当你有一个表达式或函数调用返回一个值并希望调用(可能或总是)static
函数时,.
表示法可能会阻止你需要使用{{1或者一个支持模板来访问该类型,这样您就可以使用decltype
表示法
有时变量名称更短,更方便,或以更自我记录的方式命名
答案 3 :(得分:2)
也可以使用类的对象调用静态方法,就像可以在Java中完成一样。不过,你不应该这样做。使用范围运算符,如Test::DoCrash();
也许您会想到命名空间:
namespace Test {
void DoCrash() {
std::cout << "Crashed!!" << std::endl;
}
};
如果函数没有使用Test::DoCrash();
显式导入到调用者的范围内,那么只能由using directive/declaration
从该命名空间外部调用。