C++隱藏與覆蓋
問題與原因
- 最近在做某個項目的單元測試,遇到了一個問題:Mock掉一個類之後,代碼執行時沒有走Mock後的函數。
Class XXX
{
private:
Test* m_test;
}
Class TestMock : public Test
{
public:
void f()
{
}
}
# Gtest 部分大概
#define private public
#define protected public
#include "XXX.h"
#undef private
#undef protected
TEST_F(XXX, XXXX)
{
XXX* a = new XXX();
a->m_test = new TestMock();
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();
Parent* p = new Child();
p->f();
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();
Parent* p = new Child();
p->f();
return 0;
}
- 當然對於virtual,會根據實際的類型執行。也可以理解爲動態綁定。虛函數在執行時,根據實際綁定的對象,通過虛函數表動態查找函數地址。