2013-07-16 36 views
2

示例代碼:是否改變一個方法來添加隱藏的這個指針break二進制兼容性?

// Base.hpp 
class Base 
{ 
    public: 
    void changeInternals(); 
    int readInternals(); 
    void printString(std::string& iString); 

    private: 
    int m_Internal; 
}; 

// Base.cpp 
void Base::changeInternals() 
{ 
    m_InternalValue = 5; 
} 
int Base::readInternals() 
{ 
    return m_InternalValue; 
} 
void Base::printString(std::string& iString) 
{ 
    std::cout << iString << std::endl; 
} 

我理解的是,根據與克優化++,第一兩個成員函數(changeInternal和readInternal)將具有「這個」指針作爲函數參數的一部分,所以它可以訪問成員變量m_Internal。但是,第三個成員函數printString不需要查看成員變量,因此在參數中不會有這個指針?

在這種情況下,如果我們這樣改變:

void Base::printString(std::string& iString) 
{ 
    std::cout << boost::lexical_cast<std::string>(m_Internal) << std::endl; 
} 

成員函數現在需要訪問m_Internal,因此就需要這個函數的調用者把「這個」指針的值成寄存器。

我希望它可以打破二進制兼容性,但我似乎無法找到這「二元相容性陷阱」的任何名單。是否有要求所有成員函數,不管是否觸及內部函數,都有這個指針?在覈心中檢查gdb輸出(我不能在這裏悲傷地複製/粘貼:(對不起)意味着沒有。

爲了這個問題的目的,請假定這裏沒有發生內聯(通過GCC never_inline屬性)

+2

隱式參數總是存在。否則,不可能統一使用指向成員函數的指針。 – juanchopanza

+0

@juanchopanza:不正確。考慮一個將函數標記爲「不需要這個」的編譯器,這是一個純粹的優化。 **知道調用這個函數的調用者可能會忽略這個'this'的初始化,而調用者通過指針必須假定它是需要的。一般來說,您不能認爲通過指針進行的呼叫與直接呼叫完全相同。特別是,多重遺傳PTMF通常需要存根/蹦牀。 – MSalters

+1

@Mike B:你的真實代碼中的頭文件中的方法的實現是?如果是這樣,那麼對二進制兼容性沒有多少意義。如果將實現放置到.cpp文件中,這樣纔有意義,因此「使用編譯器」不會看到它。如果實現位於頭文件中,則需要編譯所有使用代碼(如果更改它)...所以二進制兼容性無關緊要。 – mmmmmmmm

回答

2

的成員函數是ALWAYS [1]稱爲與this指針,它是否被使用或沒有。這使得編譯器不必「知道」一些功能是否使用this指針或不是,考慮這樣一種情況:函數僅作爲頭文件中的聲明包含,並且實際實現在不同的源文件中分別編譯 - co如何mpiler知道嗎?或者在函數是虛擬的情況下,有多個可能的類,其中一些可以使用,其中一些類不會在成員函數中使用this(隱式地)。

這並不適用於static成員函數 - 這就是static成員函數點的一部分。

[1]當然,在編譯器可以「看到」函數的源代碼,它可能選擇內聯實際功能,並且如果不使用this指針,就可以的情況下然後作爲內聯過程的一部分被刪除。但是這再次不是兼容性的中斷。