考虑以下两种结构:
struct Potential{
virtual double energy(int full_system, int particle_id)=0;
double energy(int full_system){
int n_particles=100;
double E=0.0;
for (int particle_id=0; particle_id<n_particles; particle_id++){
E+=energy(full_system, particle_id);
}
return E;
}
};
struct MorsePotential: Potential{
//constructor
MorsePotential (){}
//implementing the virtual function
double energy(int full_system, int particle_id){
return 10.0;
}
};
第一个,
Potential
有两个功能,都叫energy
。第一个是虚拟的,应该在所有子结构中实现。第二个应该由所有孩子继承。请注意,第二个调用父级中的第一个。
MorsePotential
是 Potential
的子级,并实现其父级的虚拟 energy
函数。但是,当使用 MorsePotential
时,我收到编译错误。代码如下:
MorsePotential mpotential;
std::cout<<mpotential.energy(0,0)<<std::endl; //works
std::cout<<mpotential.energy(0)<<std::endl; //gives compiler error
给出错误:
inherit.cc: In function ‘int main()’:
inherit.cc:35:32: error: no matching function for call to ‘MorsePotential::energy(int)’
35 | std::cout<<mpotential.energy(0)<<std::endl;
| ^
inherit.cc:25:9: note: candidate: ‘virtual double MorsePotential::energy(int, int)’
25 | double energy(int full_system, int particle_id){
| ^~~~~~
inherit.cc:25:9: note: candidate expects 2 arguments, 1 provided
我很困惑,因为第一行编译了,我可以调用
mpotential.energy(0,0)
,即虚函数的实现。然而,子级无法找到 mpotential.energy(0)
,即在其父类中实现的函数。
我想知道是什么原因导致这个错误?一开始我以为父类中可能不允许调用虚函数,但是定义
MorsePotential mpotential;
编译所以好像可以实例化子类。
这就是名称查找的工作原理。名称查找不考虑参数。它只查找被调用函数的名称。您调用
energy
,找到 MorsePotential::energy
,在考虑基类范围之前停止名称查找。
您可以通过 using 声明将名称从基类拉到派生类范围:
struct MorsePotential: Potential{
using Potential::energy; // <-------
//implementing the virtual function
double energy(int full_system, int particle_id){
return 10.0;
}
};
(您不应实现与编译器生成的构造函数具有相同功能的构造函数。)
请注意,如果您通过引用使用实际的多态性,则不会出现问题:
void foo(Potential& p) {
p.energy(42); // OK, also with your code
}