简体   繁体   English

重载虚函数集的部分继承

[英]partial inheritance of set of overloaded virtual functions

I thought I understood inheritance, and virtual functions, and function overloading, but I've got a case where something about the interplay between these features is eluding me. 我以为我理解了继承,虚函数和函数重载,但我有一个案例,其中有关于这些特性之间的相互作用的事情让我望而却步。

Suppose I've got a simple base class containing an overloaded virtual function, and a second class derived from it: 假设我有一个包含重载虚函数的简单基类,以及从中派生的第二个类:

class b {
 public:
    virtual int f() { return 1; }
    virtual int f(int) { return 2; }
};


class d : public b {
 public:
    virtual int f(int) { return 3; }
};

Notice that the derived class d overrides only one of the overloaded virtual functions. 请注意,派生类d仅覆盖其中一个重载的虚函数。

I can instantiate an object of class d and invoke f(int) on it, no problem: 我可以实例化一个类d的对象并在其上调用f(int) ,没问题:

d x;
std::cout << x.f(0) << std::endl;

But when I try to call the 0-argument function: 但是当我尝试调用0参数函数时:

std::cout << x.f() << std::endl;

it fails! 它失败! gcc says "no matching function for call to 'd::f()'; candidates are: virtual int d::f(int)". gcc说“没有匹配函数来调用'd :: f()';候选者是:virtual int d :: f(int)”。 clang says "too few arguments to function call, expected 1, have 0; did you mean 'b::f'?" clang说“函数调用的参数太少,预期为1,有0;你的意思是'b :: f'吗?” Even though d is derived from b which has a 0-argument f() method, the compiler is ignoring that, and trying to call d 's 1-argument method instead. 尽管d是从具有0参数f()方法的b派生的,但编译器忽略了这一点,并试图调用d的1参数方法。

I can fix this by repeating the definition of the 0-argument function in the derived class: 我可以通过重复派生类中的0参数函数的定义来解决这个问题:

class d : public b {
 public:
    virtual int f() { return 1; }
    virtual int f(int) { return 3; }
};

Or, as suggested by clang's error message, I can use a goofy disambiguation syntax that I never would have guessed would work: 或者,正如clang的错误消息所示,我可以使用一种愚蠢的消歧语法,我从来没有猜到它会起作用:

std::cout << x.b::f() << std::endl;

But my question is, what rule did I break, and what is that rule trying to enforce/protect/defend? 但我的问题是,我打破了什么规则,试图强制执行/保护/捍卫的规则是什么? What I thought I was trying to do here was exactly the sort of thing I thought inheritance was for. 我以为我试图在这里做的就是我认为继承的那种东西。

This is known as name hiding . 这称为名称隐藏

When you declare a function with the same name in the derived class, all functions with the same name in the base are hidden. 在派生类中声明具有相同名称的函数时,将隐藏基础中具有相同名称的所有函数。

In order to gain unqualified access to them, add a using declaration into your derived class: 要获得对它们的非限定访问权限,请在派生类中添加using声明:

class d : public b {
 public:
    using b::f;
    virtual int f(int) { return 3; }
};

Some explanation in addition to @TartanLlama's answer: 除了@ TartanLlama的答案之外还有一些解释:

When the compiler has to resolve the call to f , it does three main things, in order: 当编译器必须解析对f的调用时,它按顺序执行三个主要操作:

  1. Name lookup. 名称查找。 Before doing anything else, the compiler searches for a scope that has at least one entity named f and makes a list of candidates. 在执行任何其他操作之前,编译器会搜索至少包含一个名为f实体的范围,并生成候选列表。 In this case, name lookup first looks in the scope of d to see if there is at least one member named f ; 在这种情况下,名称查找首先查看d的范围,以查看是否至少有一个名为f成员; if there weren't, base classes and enclosing namespaces would be considered in turn, one at a time, until a scope having at least one candidate was found. 如果没有,则将依次考虑基类和封闭名称空间,一次一个,直到找到至少有一个候选的作用域。 In this case, though, the very first scope the compiler looks in already has an entity named f , and then Name lookup stops. 但是,在这种情况下,编译器查看的第一个作用域已经有一个名为f的实体,然后名称查找停止。

  2. Overload resolution. 过载分辨率。 Next, the compiler performs overload resolution to pick the unique best match out of the list of candidates. 接下来,编译器执行重载决策以从候选列表中选择唯一的最佳匹配。 In this case, the count of argument does not match, so it fails. 在这种情况下,参数计数不匹配,因此失败。

  3. Accessibility checking. 辅助功能检查。 Finally, the compiler performs accessibility checking to determine whether the selected function can be called. 最后,编译器执行可访问性检查以确定是否可以调用所选函数。

Reference for Name lookup 名称查找的参考

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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