以下在MSVC2008和MSVC2010中可以正常工作:
class Foo {
public:
static void FuncA(void) {
FuncB(); // "FuncB()" NOT DECLARED YET? WORKS, MSVC2008
}
static void FuncB(void);
};
是的,这有点奇怪:
FuncA()
调用FuncB()
,即使(此时)FuncB()
尚未声明。但是,MSVC2008和MSVC2010认为很好。显然,
gcc
认为这不好– FuncB was not declared in this scope
。问题:我有一堆这样的东西,声明它们并稍后对其进行定义将是“痛苦”。此外,很难正确地“排序”它们,因此每个函数仅在声明函数后才调用它们。 但是,我想我需要先声明然后定义定义?
这些函数是否为模板或是否在模板类中定义的规则是否不同?
具体来说,我注意到Microsoft非常“后期编译”,它接受大量的内部耦合代码,并且LATER会解析(在编译时,触发模板参数化),而
gcc
似乎希望现在编译“查看”代码(为确保正确性而进行的初始遍历,以及在参数化/调用过程中的遍历)。(当我们将Microsoft代码移植到Linux / gcc时,就会出现此问题。)
===更新===
以下是我们(在此代码移植工作中)拥有的“替代”方案,您的答案是否会基于这些方案而改变?
// Alternate-Scenario-B
class Foo2 {
public:
template<typename SOME_TYPE>
static void FuncA(const SOME_TYPE& some_type) {
FuncB(some_type); // "FuncB()" NOT DECLARED YET? WORKS, MSVC2008
}
template<typename SOME_TYPE>
static void FuncB(const SOME_TYPE& some_type);
};
...和:
// Alternate-Scenario-C
template<typename SOME_TYPE>
class Foo3 {
public:
static void FuncA(const SOME_TYPE& some_type) {
FuncB(some_type); // "FuncB()" NOT DECLARED YET? WORKS, MSVC2008
}
static void FuncB(const SOME_TYPE& some_type);
};
=== UPDATE + 2 ===
感谢您的评论,在共识看来这是有效的C++代码,并且应该起作用(如@Adam所建议的,函数“defined-inline”的行为应类似于在类之后定义的行为,并且应能够调用已定义的函数在该内联定义之后的类接口(interface)中)。
更多信息:
是的,我确实在
FuncA()
内联实现的第一个示例中遇到了此编译错误:'FuncB' is not a member of 'Foo'
...使用:
gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
(回想一下,这适用于MSVC2008 / MSVC2010)。
现在我意识到我的代码示例(上面)是不够的(上面的示例未在
gcc
上显示此错误),这里有一些更多详细信息:Foo
具有一个基类(我认为应该没关系)Foo
定义了通过这些函数传递的内部enum
(我认为这不重要)一个更完整的代码示例将是(我对此并不感到骄傲):
#define FOO_FUNCS(CLASS_NAME,CLASS_ENUM) \
static void FuncA(CLASS_ENUM value_enum) { \
FuncB(value_enum); /*PROBLEM*/ \
} \
static void FuncB(CLASS_ENUM value_enum) { \
FuncC(value_enum); \
} \
/*...THERE ARE 56 FUNCS IN THIS MACRO, THREE LINES EACH...*/
class Foo : public FooParent {
public:
enum FooEnum { FOO_ONE, FOO_TWO };
FOO_FUNCS(Foo,FooEnum) // EXPAND THE 56 FUNCS
};
代码强度:
FooParent
基类具有要与(许多)派生类“共享”的实现。派生的类定义了自己的enum
值。使用这些enum
值的函数是通过宏实现的(因为FooParent
不是template<>
,并且不能依赖于派生的enum
)。好奇的行为:
FooA(){FooB();}
嵌套引用仅由“几行”定义为“稍后”的函数,则gcc
可以正常编译。但是,如果尚未声明的功能要晚得多,例如Foo2(){Foo53();}
,则gcc
会得出结论Foo53()
不是该类的成员(而是它)。 我认为这是怎么回事:
\
转义行结尾),则gcc
可以正常编译。 因此,我认为(代码移植)答案是:
FooParentBase<>
派生的FooParent
模板类,我们从中派生Foo
,这需要typename Foo::enum
作为模板参数我对这些更改感到满意(我不喜欢宏),但是我觉得
gcc
在这里似乎有问题很奇怪。还有其他建议解决此问题吗? (以上是否重构了您要做的事情?)
最佳答案
您的代码对我来说看起来完全合法。应该将类定义中的内联定义视为等同于在类定义之后立即使用内联定义的声明(到那时,FuncB()的声明将可用)。
我的GCC版本将此代码视为有效(您发布的所有三个示例,当然,假设我提供了每个FuncB()的简单实现)。
~$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
...
我相信这里需要更多信息。也许发布您的GCC版本和您看到的特定错误消息。
========稍后更新========
我已经尝试了您的最新示例,其中包含70个宏函数,但在gcc 4.6.3中它仍然对我有用。这是我尝试的测试(以明显的方式缩短了宏):
#include <iostream>
using std::cout;
struct FooParent {
static void Func71( int ) {
cout << "Called\n";
}
};
#define FOO_FUNCS(CLASS_NAME,CLASS_ENUM) \
static void Func1(CLASS_ENUM value_enum) { \
Func2(value_enum); /PROBLEM/ \
} \
static void Func2(CLASS_ENUM value_enum) { \
Func3(value_enum); \
} \
/* Functions Func3...Func69 snipped */ \
static void Func70(CLASS_ENUM value_enum) { \
Func71(value_enum); \
} \
/...THERE ARE 70 FUNCS IN THIS MACRO, THREE LINES EACH.../
class Foo : public FooParent {
public:
enum FooEnum { FOO_ONE, FOO_TWO };
FOO_FUNCS(Foo,FooEnum) // EXPAND THE 70 FUNCS
};
int main() {
Foo::Func1(Foo::FOO_ONE);
}
关于c++ - C++内联函数可以调用稍后在 header 中声明的函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15749468/