为什么成员函数名称查找保留在父类中?

tma*_*ric 2 c++ inheritance

动机,如果有帮助的话::我有一些结构成员函数,它们是径向基函数内核。在数值模拟中,它们被称为1e06 x 15 x 1e05次。对于许多函数调用,我都不希望依靠去虚拟化来内联虚拟函数。同样,结构(RBF内核)已经用作较大插值类的模板参数。

最小的工作例子

我有一个g()始终不变的函数,并且我想重用它,因此我将其打包在基类中。

该函数g()调用f()派生类中不同的函数。

我不想virtual在运行时使用函数来解析函数名称,因为这会产生额外的费用(我在代码中对其进行了度量,但会产生影响)。

这是示例:

#include <iostream>

struct A 
{
    double f() const { return 0; };

    void g() const
    {
        std::cout << f() << std::endl; 
    }
};

struct B : private A
{
    using A::g; 
    double f() const { return 1; };
};

struct C : private A
{
    using A::g;
    double f() const { return 2; };
};

int main()
{
    B b; 
    C c; 

    b.g(); // Outputs 0 instead of 1 
    c.g(); // Outputs 0 instead of 2
}
Run Code Online (Sandbox Code Playgroud)

我希望名称解析机制能够弄清楚我想使用“ A :: g()”,但是然后返回到“ B”或“ C”来解析“ f()”函数。大概是这样的:“当我在编译时知道一个类型时,我将尝试首先解析该类型中的所有名称,然后从缺少某些对象的对象/父对象中进行名称查找,然后返回到我从中被调用的类型”。但是,似乎弄清楚了使用了“ A :: g()”,然后它位于“ A”中,只是选择了“ A :: f()”,即使实际调用“ g()”来自“ B”和“ C”。

可以使用虚函数解决此问题,但是我不理解,并且想知道在编译时知道类型时名称查找遵循父类的原因

没有虚拟功能怎么办?

Sne*_*tel 5

这是CRTP的标准任务。基类需要知道对象的静态类型是什么,然后将其自身强制转换为静态类型。

template<typename Derived>
struct A
{
    void g() const
    {
        cout << static_cast<Derived const*>(this)->f() << endl;
    }
};

struct B : A<B>
{
    using A::g; 
    double f() const { return 1; };
};
Run Code Online (Sandbox Code Playgroud)

另外,回应您写的评论(也许这是您的真正问题?),

您能告诉我名称查找坚持基类的原因是什么,而不是一旦查找g()便返回到派生类?

因为类旨在用于面向对象的编程,而不是用于代码重用。有A需求的程序员必须能够理解他们的代码在做什么,这意味着子类不应能够从基类中任意重写功能。这就是virtual就是,真正做到:A给予其子类的权限覆盖特定成员。任何A没有为此选择的东西,他们都应该能够依靠。

在您的示例中考虑:如果B后来的作者添加了一个恰巧被称为的整数成员,该endl怎么办?那应该休息A吗?是否应该B关心所有的私有成员名称A?而且,如果的作者A想要添加成员变量,他们是否应该能够以不破坏某些子类的方式添加成员变量?(答案是“否”,“否”和“是”。)