簡體   English   中英

.cpp文件中的C ++內聯成員函數

[英]C++ inline member function in .cpp file

我知道按定義,內聯成員函數應該進入標題。 但是如果不能將函數的實現放入標題呢? 讓我們來看看這種情況:

檔案啊

#pragma once
#include "B.h"

class A{
    B b;
};

文件Bh

#pragma once

class A; //forward declaration

class B{
    inline A getA();
};

由於循環包含我必須把getA的實現

B.cpp

#include "B.h"
#include "A.h"

inline A B::getA(){
    return A();
}

編譯器內聯getA嗎? 如果是這樣,哪個內聯關鍵字是重要的(標題中的那個或.cpp文件中的那個)? 是否有另一種方法將內聯成員函數的定義放入其.cpp文件中?

引用C ++ FAQ

注意:必須將函數的定義({...}之間的部分)放在頭文件中,除非該函數僅在單個.cpp文件中使用。 特別是,如果將內聯函數的定義放入.cpp文件中並從其他.cpp文件中調用它,則會從鏈接器中獲得“未解析的外部”錯誤。

只要發現任何內聯函數的使用,編譯器就需要查看內聯函數的定義 如果內聯函數放在頭文件中,這通常是可能的。

編譯器內聯getA嗎?

不,除非使用getA()在B.cpp本身。

如果是這樣,哪個內聯關鍵字是重要的關鍵字(標題中的那個或cpp中的那個)?

最佳實踐 :僅限於類體外的定義。

有沒有其他方法將內聯成員函數的定義放入其cpp文件中?

不,至少我不知道。

它不能超出B.cpp的范圍。 編譯器在每個編譯單元的基礎上運行,即它單獨編譯每個.cpp文件,因此如果它編譯C.cpp,它將沒有getA()的代碼可用,並且需要執行函數調用和讓鏈接器修復它(或者,如果它真的把你帶走了並嘗試內聯,它將最終出現鏈接器錯誤inline具有與static類似的特性)。

唯一的例外是LTCG,即鏈接時代碼生成,可在較新的編譯器上使用。

在這種情況下,一種方法是使用包含內聯代碼的另一個頭文件(有時命名為* .inl文件)。

編輯:至於哪個內聯是相關的 - 它是類定義中的那個,即在頭文件中。 請記住,許多編譯器對可以和應該內聯的內容有自己的想法。 例如,gcc可以完全禁用內聯(-O0),或者它可以內聯任何它認為值得內聯的內容(如-O3)。

我會從相反的方向去做這件事。

不要在函數中添加內聯聲明(除非你需要)。

您需要將內聯聲明添加到函數/方法的唯一時間是在頭文件中但在類聲明之外定義函數。

XH

class X
{
    public:
        int getX()   { return 4;} // No inline because it is part of the class.
                                  // The compiler knows that needs an inline tag
        int getY();
        int getZ();
};

inline
int X::getY()  { return 5;}       // This needs to be explicitly declared inline.
                                  // Otherwise the linker will complain about
                                  // multiple definitions in compilation units.

X.cpp

 // Never declare anything inline in the cpp file.

 int X::getZ() { return 6; }

給你更具體的案例。
刪除所有內聯規范。 他們沒有做你認為他們正在做的事情。

目前,大多數編譯器都可以在鏈接時執行內聯,以及編譯時。 如果您的函數可能會受益於內聯,那么鏈接時優化器很可能就是這樣做的。

當鏈接器到達它時,編譯器輸出的內聯狀態並不多,除了編譯器將某些對象標記為可收集,例如因為內聯函數或類模板實例出現在多個編譯單元中,或者當多個符號共享一個名稱時,它應該引發錯誤,例如兩次定義的主函數。 這些都不會影響它將生成的實際代碼。

這是我做的方式。

檔案啊

#pragma once
#include "B.h"

class A {
    B b;
};

文件Bh

#pragma once

class B {
public:
    template<class T> inline T getA() {
        assert(NULL); // Use 'getA<A>()' template specialization only!
        return NULL;
    }
};

class A; // Forward declaration
template<> inline A B::getA<A>();

文件Ch

#pragma once
#include "A.h"
#include "B.h"

// Implement template specialization here!
template<> inline A B::getA<A>() { return A(); }

只需包含“Ch”文件即可使用getA()方法。 原始代碼的唯一變化是getA()方法必須定義為public而不是private。

但是,正如你們許多人所解釋的那樣,這並不是很有用。

ISO / IEC 14882:2014

每個程序應該只包含該程序中使用的每個非內聯函數或變量的一個定義; 無需診斷。 該定義可以在程序中明確顯示,可以在標准或用戶定義的庫中找到,或者(在適當的時候)隱式定義(見12.1,12.4和12.8)。 內聯函數應在每個使用它的翻譯單元中定義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM