C++ 什么时候使用静态成员函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4921150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:55:21  来源:igfitidea点击:

When to use static member function?

c++functionstatic

提问by Umesha MS

Possible Duplicates:
Where would you use a friend function vs a static function?
C++: static member functions

可能的重复:
你会在哪里使用友元函数和静态函数?
C++:静态成员函数

When is it appropriate to use a static member function in C++? Please give me a real world example.

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

采纳答案by CashCow

Good uses of static member functions:

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

  • Meta-programming. Real-world example is template std::char_traits. All member functions are static
  • Making it a static member function gives it access to private members of the class, although a friend would suffice here too
  • A protected static member function thus is accessible only to the class and classes derived from it.
  • 元编程。真实世界的例子是模板 std::char_traits。所有成员函数都是静态的
  • 使它成为静态成员函数可以访问类的私有成员,尽管在这里也可以使用朋友
  • 因此,受保护的静态成员函数只能被类和从它派生的类访问。

Note that the last case applies to a protected static member function but not a private one. In the latter case you would just put it into the compilation unit of the class, hiding it away as an implementation detail. For a protected one though you want it to be visible, albeit in a restricted way.

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

A typical case of that one is "cheating" the lack of inheritance of friendship.

一个典型的例子就是“欺骗”缺乏友谊的传承。

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
}

回答by daramarak

The natural place to use it is when you cannot use a free function because you need to access internals of the class. The most typical example of this is a builder function as below. The constructor of Foo is private to make sure that it is not constructed in any other way than with the builder function.

使用它的自然场所是当您无法使用自由函数时,因为您需要访问类的内部结构。最典型的例子是下面的构建器函数。Foo 的构造函数是私有的,以确保它不是用 builder 函数以外的任何其他方式构造的。

#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;
}

A typical use of that is earlier mentioned Singleton pattern. When you do not have to access protected and private parts of the class, static member functions is not necessary (free functions can be used), but there is some that uses static member functions also when it is within the domain of the class but not restricted/logical to use the function on a single instance.

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

回答by Zac Howland

A common example you'll find (in a real world example) is when you are creating a thread. The common thread API's (POSIX/pthreads, Boost, and Win32 CreateThread) all require a specific signature. The only way to obtain that signature in a member function is by making the function static.

您会发现的一个常见示例(在实际示例中)是在创建线程时。公共线程 API(POSIX/pthreads、Boost 和 Win32 CreateThread)都需要特定的签名。在成员函数中获得该签名的唯一方法是将函数设为静态。

回答by Patryk

You may want to use the function without an object instantiated. Also if the function is called from another static function it must be static.

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

回答by User234

A typical example can be a singleton class where the static GetInstance() method returns the singleton instance of the class.

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

class Singleton
{
    static Singleton instance;

    private Singleton()
    {
    }

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

      return instance;
    }
}

回答by Ricko M

Please look up a design pattern called singleton.In short, It's one way to restrict creation of object. Thus the only way to create an object is to call a C++ member function which is static.

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

回答by Ricko M

I misread your question and answered when it's appropriate to use static functions.

我误读了您的问题,并在适合使用静态函数时回答了问题。

You meant static member functions. here's an example of when to use a static member function - to wrap a thread call inside a class, so that your thread has access to your class...:

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

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;
}

Here was my answer for plain old static functions.. I use static functions where it doesn't make sense for that function to belong to a class.

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

I generally tend to add these functions to a custom namespace. The following static function sample is part of a namespace I call ShellUtils:

我通常倾向于将这些函数添加到自定义命名空间中。以下静态函数示例是我称为 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;

}

}