何时使用静态成员函数?

时间:2011-02-07 12:14:22

标签: c++ function static

  

可能重复:
  Where would you use a friend function vs a static function?
  C++: static member functions

何时在C ++中使用静态成员函数是否合适?请给我一个真实世界的例子。

7 个答案:

答案 0 :(得分:12)

静态成员函数的良好用途:

  • 元编程。真实世界的例子是模板std :: char_traits。所有成员函数都是静态的
  • 使它成为一个静态成员函数,可以访问该类的私有成员,虽然朋友也可以在这里使用
  • 因此,受保护的静态成员函数只能由从中派生的类和类访问。

请注意,最后一种情况适用于受保护的静态成员函数,但不适用于私有函数。在后一种情况下,您只需将其放入类的编译单元中,将其作为实现细节隐藏起来。对于受保护的,虽然你希望它是可见的,尽管是有限的。

一个典型的案例是“欺骗”缺乏友谊的继承。

class B
{
   friend class A;
   // lots of private stuff
};

class A
{
protected:
   static void callsSomePrivateMembers( B& b );
};

class AChild : public A
{
   void foo( B& b );
}

void AChild::foo( B& b )
{
      // AChild does not have private access to B as friendship is not inherited
      // but I do have access to protected members of A including the static ones

    callsSomePrivateMembers( b ); // get to call them through a back-door
}

答案 1 :(得分:6)

使用它的自然之处在于,当您无法使用免费功能时,因为您需要访问该类的内部。最典型的例子是构建函数,如下所示。 Foo的构造函数是私有的,以确保它不是以构造函数之外的任何其他方式构造的。

#include <iostream>

class Foo {
public:
  static Foo* createFoo() {return new Foo();}
private: 
  Foo() {}
};

int main() {
  //Foo nonBuiltFoo; //wont compile
  Foo* freshFoo = Foo::createFoo();
  delete freshFoo;
  return 0;
}

前面提到的Singleton模式的典型用法。当您不必访问类的受保护和私有部分时,不需要静态成员函数(可以使用自由函数),但是当它在类的域内时,也有一些使用静态成员函数但不是限制/逻辑以在单个实例上使用该函数。

答案 2 :(得分:4)

您将找到的一个常见示例(在实际示例中)是您创建线程时。公共线程API(POSIX / pthreads,Boost和Win32 CreateThread)都需要特定的签名。在成员函数中获取该签名的唯一方法是使函数保持静态。

答案 3 :(得分:3)

您可能希望在没有实例化对象的情况下使用该函数。此外,如果从另一个静态函数调用该函数,它必须是静态的。

答案 4 :(得分:3)

典型示例可以是单例类,其中静态GetInstance()方法返回类的单例实例。

class Singleton
{
    static Singleton instance;

    private Singleton()
    {
    }

    static Singleton & GetInstance()
    {
      if(instance == null)
        instance = new Singleton();

      return instance;
    }
}

答案 5 :(得分:2)

我误读了你的问题并在适当的时候回答了使用静态功能。

您的意思是静态成员函数。这里是一个何时使用静态成员函数的示例 - 在类中包装线程调用,以便您的线程可以访问您的类......:

static unsigned WINAPI ArchiveAgent::LogMsgPump(PVOID pData)
{
    ArchiveAgent* pSmith = reinterpret_cast<ArchiveAgent*>(pData);

    if( pSmith )
        pSmith->LogMsgPump();
    else
        return -1;

    return 0;
}

unsigned WINAPI ArchiveAgent::LogMsgPump()
{
    CoInitializeEx(NULL, COINIT_MULTITHREADED);

    // ....

    CoUninitialize();
    return 0;
}

这是我对普通旧静态函数的回答.. 我使用静态函数,因为该函数属于一个类是没有意义的。

我通常倾向于将这些函数添加到自定义命名空间。以下静态函数示例是我称为ShellUtils的命名空间的一部分:

static HRESULT CreateFolder( CString & sPath )
{
// create the destination folder if it doesn't already exist

HRESULT hr      = S_OK;
DWORD   dwError = 0;

if( sPath.GetLength() == 0 || sPath.GetLength() < 2 )                   
    return E_UNEXPECTED;

if( GetFileAttributes( (LPCWSTR) sPath ) == INVALID_FILE_ATTRIBUTES )
{           
    dwError = SHCreateDirectoryEx(NULL, (LPCWSTR)sPath, NULL);

    if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_EXISTS && dwError != ERROR_ALREADY_EXISTS)
        hr = HRESULT_FROM_WIN32(dwError);
}

return hr;

}

答案 6 :(得分:2)

请查看名为singleton的设计模式。简而言之,这是限制对象创建的一种方法。因此,创建对象的唯一方法是调用静态的C ++成员函数。