在C++中,在头文件中声明静态方法并在源文件中定义它是如何实现的?

166

我在使用C++中的静态方法方面遇到了一些问题。

示例 .h:

class IC_Utility {
public:
    IC_Utility();
    ~IC_Utility();

    std::string CP_PStringToString( const unsigned char *outString );
    void CP_StringToPString( std::string& inString, unsigned char *outString, short inMaxLength );
    static void CP_StringToPString( std::string& inString, unsigned char *outString);
    void CP_StringToPString( FxString& inString, FxUChar *outString);

};

示例 .cpp:

static void IC_Utility::CP_StringToPString(std::string& inString, unsigned char *outString)
{
    short       length = inString.length();

   if( outString != NULL )
    {
        if( length >= 1 )
            CPLAT::CP_Utility::CP_CopyMemory( inString.c_str(), &outString[ 1 ], length );

            outString[ 0 ] = length;
    }
}

我想要进行如下的函数调用:

IC_Utility::CP_StringToPString(directoryNameString, directoryName );

但是我遇到了一个错误:

error: cannot declare member function 'static void IC_Utility::CP_StringToPString(std::string&, unsigned char*)' to have static linkage

我不理解为什么我不能这样做。有人能帮我理解为什么以及如何实现我想要的吗?


3
首先,你应该在.cpp文件中移除static关键字。C++不允许它。 - B. Decoster
12
可以考虑用 /* static */ 代替它。我喜欢在 .h 和 .cpp 文件中使用相同的修饰符和默认参数。 - David Thornley
3
TL;DR:在头文件 .h 中保留 static,它的意思是“附加到类,而不是任何对象”,在 .cpp 文件中删除 static,因为它有一个不适用于这里的不同含义。 - Stéphane Gourichon
5个回答

265

在方法定义中移除static关键字,只在类定义中保留它。

.cpp文件中放置static关键字意味着某个函数具有静态链接,即仅可从同一文件中的其他函数访问。


1
啊,明白了,方法定义中的 static 意味着只有该类中的其他方法才能访问该静态方法,而不能从该类外部访问。 - ABV
14
不是其他类成员函数,而是在.cpp文件中的其他函数。无论如何,在C++中你不应该这样做。如果你想让一个C++函数拥有内部链接性,你应该考虑将它放在某个匿名命名空间中。在.cpp文件中使用static仅仅是为了与C语言保持向后兼容性。 - x13n
1
只是出于好奇...如果我直接在类中定义静态成员(在.h文件中),我如何使用静态链接? - lumbric
你不能这样做。而且这样做也没有意义,因为将程序链接在一起会导致出现未解决的外部符号。 - x13n

48

关键字staticvirtual不应在定义中重复使用,而且只能在类声明中使用。


14

函数定义中不需要使用 static 关键字


0
可能最好的做法是“像标准库一样做”。也就是说:全部都是内联函数,全部都在头文件中。
// in the header
namespase my_namespace {

   class my_standard_named_class final {
public:
         static void standard_declared_defined_method () {
            // even the comment is standard
         }
   } ;

} // namespase my_namespace 

就是这么简单...


-4
静态成员函数必须引用该类的静态变量。所以在你的情况下,
static void CP_StringToPString( std::string& inString, unsigned char *outString);

由于您的成员函数 CP_StringToPstring 是静态的,因此该函数中的参数 inStringoutString 也应声明为静态。

静态成员函数不引用它正在处理的对象,而是引用您声明的变量引用其当前对象,因此会返回错误。

您可以从成员函数中删除 static,或在声明用于成员函数的参数时添加 static。


2
inString和outString是静态函数的参数。它们不是类成员,无需将它们转换为静态。 - 999k
这完全不正确。您可以在静态成员函数中放置非静态参数。但是对于类成员,您只能在函数中访问/修改静态成员。 - Zachary Kraus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接