C++隱藏與覆蓋

C++隱藏與覆蓋

問題與原因

  • 最近在做某個項目的單元測試,遇到了一個問題:Mock掉一個類之後,代碼執行時沒有走Mock後的函數。
// 要測試的類
Class XXX
{
	//...
	private:
	    // 原有的成員變量
		Test* m_test;
}

// Mock掉Test類
Class TestMock : public Test
{
	public:
		// Mock的接口
		void f() 
		{
			// ....
		}
}

# Gtest 部分大概

#define private public
#define protected public
#include "XXX.h"
#undef private
#undef protected

TEST_F(XXX, XXXX)
{
	XXX* a = new XXX();
	// 使用Mock掉的類
	a->m_test = new TestMock();
	// 調用Mock掉的接口
	a->m_test->f();
}
  • 上述代碼執行後,沒有走Mock掉的接口,而走了其父類的接口。查找問題,發現了原因。
  • 原因爲:父類的相關接口,爲普通成員函數(非虛)
class Test
{
	public:
		// 非虛函數
		void f()
		{
		}
}
  • 在繼承時,如果父類中的函數爲virtual,子類中重寫該函數後,在子類中會覆蓋掉父類的方法。
  • 在繼承時,如果父類中的函數爲非virtual,子類中重寫該函數後,在子類中會隱藏掉父類的方法。
  • 覆蓋和隱藏,是有區別的。

覆蓋與隱藏的區別

  • 發生覆蓋時,會根據對象的實際類型去執行相應的函數。如果該類型中,沒有找到相關函數,則到其父類中尋找。
#include<iostream>

class Parent
{
    public:
        virtual void f()
        {
            std::cout << "hello" << std::endl;
        }    
};

class Child : public Parent
{
    public:
        void f() {
            std::cout << "world" << std::endl;
        }

};

int main()
{
Parent a;
a.f();	// 輸出 hello

Parent* p = new Child();
p->f();	// 輸出 world


return 0;
}

  • 發生隱藏時,會根據對象聲明的類型,去執行相應的函數。如果該類型中,沒有找到相關函數,則到其父類中尋找。
#include<iostream>

class Parent
{
    public:
        void f()
        {
            std::cout << "hello" << std::endl;
        }    
};

class Child : public Parent
{
    public:
        void f() {
            std::cout << "world" << std::endl;
        }

};

int main()
{
Parent a;
a.f();	// 輸出 hello

Parent* p = new Child();
p->f();// 輸出 hello


return 0;
}

  • 當然對於virtual,會根據實際的類型執行。也可以理解爲動態綁定。虛函數在執行時,根據實際綁定的對象,通過虛函數表動態查找函數地址。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章