簡體   English   中英

投給孩子 object 進行測試 - 此代碼是否符合標准?

[英]Cast to child object for testing - is this code standard-conforming?

TL;博士

這個轉換/函數調用是合法的、符合標准的 C++11/14 代碼嗎?
如果沒有,是否沒有虛函數(如果std::is_standard_layout<Module>變為真)?
注意:它適用於我迄今為止測試過的每個編譯器......

class Module
{
protected:
    virtual float protectedVirtualFunction(float f) { return f*f*f; }
    float protectedFunction(float f) { return f*f; }
};

class ModuleTester : public Module // consists of ONLY aliases
{
public:
    using Module::protectedFunction;
    using Module::protectedVirtualFunction;
};

int main()
{
    Module module;  //assume this is a pre-existing instance
    // Is this legal?
    ModuleTester* testerMask = static_cast<ModuleTester*>(&module); 
    testerMask->protectedFunction(4.4f);
    testerMask->protectedVirtualFunction(4.4f);
}

附加信息

通常,我的目標是僅在編寫單元測試時測試公共類 API。 在某些情況下——比如當你處理無法更改的遺留代碼時——訪問私有成員更實用。

因此,假設我們無法更改設計(DI、解耦...),我看到以下解決方案:

  1. 公開私有成員(損害所有封裝)
  2. 老把戲: #define private public in test context
  3. “測試者”模式(在示例代碼中使用)

使用這種“測試者”模式的標准方式是這樣的,這應該是合法的:

    ModuleTester tester;
    tester.protectedFunction(4.4f);
    tester.protectedVirtualFunction(4.4f);

但是,有時我有一個現有的實例,如果我可以在它上面應用這個“測試器掩碼”以獲得訪問權限,那就太好了。

我的猜測是,一旦我使用虛擬功能並不再是“標准布局”,嚴格來說可能會有“未定義的行為”。 但是,如果我只在派生的 class 中定義別名,那么只要我對 Module 和 ModuleTester 使用相同的編譯器,我看不出 go 怎么會出錯。

編輯:我發現了一個類似的方法,它不使用顯式指針轉換( https://stackoverflow.com/a/1725107/649700 )。 它有效,可以說可讀性較差,並且可能不會改變“合法性”狀態。

(module.*&ModuleTester::protectedVirtualFunction)(4.4f);

其他一些有好處的 SO 問題: reinterpret_cast from object to first memberHow do I unit test a protected method in C++?

這將是未定義的行為,因為&module沒有指向 object ModuleTester的子對象:

8.5.1.9 Static 鑄件 [expr.static.cast]
11 “指向 cv1 B 的指針”類型的純右值,其中 B 是 class 類型,可以轉換為“指向 cv2 D 的指針”類型的純右值,其中 D 是從 B 派生的 class(第 13 條),如果 cv2 是與 cv1 相同的 cv 限定或更高的 cv 限定。 如果 B 是 D 的虛擬基 class 或虛擬基 class 的基 class,或者如果沒有從“指向 D 的指針”到“指向 B 的指針”的有效標准轉換,則存在錯誤。 . null 指針值 (7.11) 轉換為目標類型的 null 指針值。 如果“指向 cv1 B 的指針”類型的純右值指向實際上是 D 類型 object 的子對象的 B,則生成的指針指向 D 類型的封閉 object。否則,行為未定義。

#define private public也不是一個好主意:

2 翻譯單元不得#define 或#undef 名稱在詞法上與關鍵字、表4 中列出的標識符或10.6 中描述的屬性標記相同。

暫無
暫無

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

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