我需要解释为什么以下代码无法编译。我有一个解决方法,我将在下面阐述,但我不了解原始版本的失败。
加速代码读取:概念是定义一个接口(ISomething
),然后创建一个抽象实现(ASomething
),它使用第一个函数实现第二个函数(2)
(尚未定义)一个(1)
。从抽象实现派生的完整实现(例如SomethingImpl
)必须定义第一个方法,并且可以覆盖第二个方法。
#include <iostream>
class ISomething
{
public:
virtual ~ISomething()
{ }
virtual int f(int x) = 0; // (1)
virtual int f(int x, int y) = 0; // (2)
};
class ASomething
: public virtual ISomething
{
public:
virtual int f(int x, int y) // (2)
{
return f(x) + f(y); // (3)
}
};
class SomethingImpl
: public ASomething
{
public:
virtual int f(int x) // (1)
{
return x+1;
}
};
int main()
{
SomethingImpl a;
std::cout << a.f(10) << std::endl; // (1)
std::cout << a.f(10,20) << std::endl; // (2)
return 0;
}
编译此代码会在Visual Studio 2013(Windows)和g ++ 4.4.5(Linux)上产生错误。错误非常相似,我将仅详细说明g ++输出:
$ g++ SibFun.cpp -o SibFun
SibFun.cpp: In member function ‘virtual int ASomething::f(int, int)’:
SibFun.cpp:18: error: no matching function for call to ‘ASomething::f(int&)’
SibFun.cpp:16: note: candidates are: virtual int ASomething::f(int, int)
SibFun.cpp:18: error: no matching function for call to ‘ASomething::f(int&)’
SibFun.cpp:16: note: candidates are: virtual int ASomething::f(int, int)
SibFun.cpp: In function ‘int main()’:
SibFun.cpp:36: error: no matching function for call to ‘SomethingImpl::f(int, int)’
SibFun.cpp:26: note: candidates are: virtual int SomethingImpl::f(int)
make: *** [SibFun] Error 1
我尝试在(3)
return this->f(x) + this->f(y)
使用不同的表示法,但我没有在错误消息中发生重大变化。
然而,当我将(3)
更改为return ISomething::f(x) + ISomething::f(y);
时,我才得到:
$ g++ SibFun.cpp -o SibFun
SibFun.cpp: In function ‘int main()’:
SibFun.cpp:36: error: no matching function for call to ‘SomethingImpl::f(int, int)’
SibFun.cpp:26: note: candidates are: virtual int SomethingImpl::f(int)
make: *** [SibFun] Error 1
但是!将(2)
从f
更改为g
时,所有内容都会按预期进行编译和运行。
这个乞求背后的原因是什么?为什么我不能使用f
的{{1}}名称?
答案 0 :(得分:7)
函数重载仅适用于同一范围内可见的函数:
from gensim import models
w = models.Word2Vec()
w.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)
print w["queen"]
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-3-8219e36ba1f6> in <module>()
----> 1 w["queen"]
C:\Anaconda64\lib\site-packages\gensim\models\word2vec.pyc in __getitem__(self, word)
761
762 """
--> 763 return self.syn0[self.vocab[word].index]
764
765
AttributeError: 'Word2Vec' object has no attribute 'syn0'
答案 1 :(得分:4)
两个编译失败都是出于同样的原因。当你覆盖一个虚拟成员函数时,你隐藏了另一个。在$(document.body)
:
ASomething
virtual int f(int x, int y) // (2)
{
return f(x) + f(y); // (3)
}
上的名称查找找到f
并停止,它不会继续寻找其他重载。由于ASomething::f
有两个参数,而你试图用一个参数调用它,因此错误。为了允许对基类进行重载,必须使用 using-declaration 引入基类成员函数:
ASomething::f
同样地,using ISomething::f; // NOW, ISomething::f(int ) is found by lookup
virtual int f(int x, int y)
{
return f(x) + f(y);
}
需要SomethingImpl
语句,以便using ASomething::f;
可以编译。
答案 2 :(得分:1)
问题不在于超载&#39;问题,但隐藏基类功能(见其他答案)
稍加修改的示例:
#include <iostream>
class ISomething
{
public:
virtual ~ISomething() {}
virtual int f(int x) = 0; // (1)
virtual int f(int x, int y) = 0; // (2)
};
class ASomething: public virtual ISomething
{
public:
virtual int f(int x, int y) // (2)
{
// `this->f(x)` fails:
ISomething& i = *this;
return i.f(x) + i.f(y); // (3)
}
};
class SomethingImpl: public ASomething
{
public:
virtual int f(int x) // (1)
{
return x+1;
}
};
int main()
{
SomethingImpl a;
// `a.f(10, 20)` fails:
ISomething& i = a;
std::cout << i.f(10) << std::endl; // (1)
std::cout << i.f(10, 20) << std::endl; // (2)
return 0;
}
因此,从界面调用f
可以解决冲突。虽然,您应该考虑using base::f
,如其他答案所示。