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,会根据实际的类型执行。也可以理解为动态绑定。虚函数在执行时,根据实际绑定的对象,通过虚函数表动态查找函数地址。