以下作品MSVC2008和MSVC2010 剛剛罰款:C++內聯函數調用函數可以在頭文件後面聲明嗎?
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
。
ISSUE:我有一堆這些,這將是一個「痛苦」來宣佈它們,並在以後定義它們。而且,很難對它們進行「排序」,因此每個函數在聲明之後都只會調用函數。 但是,我猜我需要首先聲明 - 然後定義 - 以後?
對於這些函數是模板還是模板或者在模板類中定義的規則是否不同?
具體來說,我注意到微軟非常「後期編譯」,它接受大量的內部耦合代碼,並且LATER解析(在編譯時,當模板參數化被觸發時),而gcc
似乎想要編譯現在當它「看到」的代碼(一個正確的初始過程,並再次在參數化/調用)。
(這個問題表現爲我們端口我們微軟的源代碼的Linux/GCC)
=== UPDATE ===
以下是 「備用」 的情況,我們有(以這個代碼移植工作),並且你的答案會基於這些變化而變化嗎?
// 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所建議的那樣,「內聯定義」的函數應該像在類之後定義的一樣,並且應該能夠在內聯定義之後調用類接口中定義的函數)。
更多信息:
是的,我確實有這樣的編譯錯誤從FuncA()
在線執行的第一個例子:
'FuncB' is not a member of 'Foo'
...使用:
gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
(回想一下,這適用於MSVC2008/MSVC2010)。
我現在意識到,我的代碼,例如(上圖)是不夠的(上面的例子中並沒有顯示在gcc
這個錯誤),這裏有更多的細節:
Foo
有一個基類(我不認爲應該的問題)Foo
定義了通過這些funcs中通過內部enum
(我不認爲這個問題)- 這些功能的「擴張」,通過一個宏(我認爲顯著 - 見以下)
- 有這些功能的56(56),(我認爲顯著 - 見下文)
一個更完整的代碼示例將是(我不是爲此感到自豪):
#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()
不是該類的成員(但它是)。
這是我認爲正在發生的事情:
- 似乎有是有很多-的代碼(56個功能),這些身體上的「一行」的問題。如果我將這些函數從宏中刪除,則和如果我刪除
\
轉義行結束,則gcc
編譯正常。
因此,我認爲(代碼移植)的回答是:
- 不要使用預處理宏
- 使從
FooParent
派生的FooParentBase<>
模板類,從我們所衍生Foo
,這就要求typename Foo::enum
作爲模板參數
我沒事這些變化(我不喜歡宏),但我覺得很奇怪的是gcc
在這裏似乎有問題。
有沒有其他建議如何解決這個問題? (上面是重新考慮你會做什麼?)
你的問題提到模板,但代碼沒有任何。也許你需要第二個代碼示例? –
@Ben,感謝,用'template <>'示例更新了問題,但我現在不認爲模板是問題的一部分(請參閱「UPDATE + 2」) – charley