繁体   English   中英

我怎么知道哪个函数会被调用?

[英]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_ContainerGet_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM