[英]How do I know which function will be called?
今天,我在代码库中发现了以下令人不安的模棱两可的情况:
class Base {
public:
virtual void Irrelevant_Function(void) = 0;
protected:
C_Container * Get_Container(void);
};
class A : public Base, public Not_Important {
public:
inline C_Container * Get_Container(void);
};
class B : public Base, protected SomethingElse {
public:
C_Container * Get_Container(void);
};
很多事情都在调用Get_Container方法,但并不总是调用正确的方法-请注意,这些函数都不是虚拟的。
我需要重命名方法Get_Base_Container
, Get_A_Container
等,以消除歧义。 C ++使用什么规则来确定应调用的函数版本? 我想从应该被调用的“已知状态”开始,然后从那里找出错误。
例如,如果我有一个指向Base的指针并调用Get_Container,则假定它只会调用该函数的Base版本。 如果我有一个指向A的指针怎么办? 指向B的指针呢? 堆上的A或B呢?
谢谢。
这取决于您如何调用该函数。 如果通过A *
, A &
或A
进行调用,则将调用A::Get_Container()
。 如果您通过Base *
, Base &
(即使它们指向/引用A
)进行调用,那么您将在调用Base::Get_Container()
。
只要不进行虚拟继承,就很容易。 如果直接使用对象,则调用该对象的方法。 如果您使用的是指针或引用,则由指针或引用的类型决定方法,而指向的对象的类型则无关紧要。
首先根据对象的静态类型查找方法。 如果那里不是虚拟的,那您就完成了:那就是调用的方法。 动态类型是虚拟方法,dynamic_cast和typeid使用的类型,并且是对象的“实际”类型。 静态类型是静态类型系统的工作方式。
A a; // Static type and dynamic type are identical.
Base &a_base = a; // Static type is Base; dynamic type is A.
a.Get_Contaienr(); // Calls A::Get_Container.
a_base.Get_Container(); // Calls Base::Get_Container.
B *pb = new B(); // Static type and dynamic type of *pb (the pointed-to
// object) are identical.
Base *pb_base = pb; // Static type is Base; dynamic type is B.
pb->Get_Container(); // Calls B::Get_Container.
pb_base->Get_Container(); // Calls Base::Get_Container.
上面我假设受保护的Base :: Get_Container方法是可访问的,否则这些将是编译错误。
在此需要注意的其他几点:
名称查找在单个作用域中进行; 例如,当在静态类型为'B'的对象上调用该方法时,编译器将考虑接口'B'以确定是否存在有效的匹配项。 如果不存在,则仅查看Base的接口以找到匹配项。 这就是为什么从编译器的角度来看,没有歧义并且可以解决调用的原因。 如果您的真实代码有重载等,则可能是一个问题。
其次,通常会忘记“ protected”关键字在类而非对象级别适用。 因此,例如:
class Base {
protected:
C_Container * Get_Container(void);
};
class B : public Base{
public:
C_Container * Get_Container(void)
{
B b;
// Call the 'protected' base class method on another object.
return b.Base::Get_Container();
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.