成员方法调用具有相同名称但不同签名的虚拟方法



我有以下头文件/源文件:

// foo.h
#ifndef __FOO_H
#define __FOO_H
#include <map>
#include <stdexcept>
template <typename T>
class FooBase {
public:
std::map<float,T> a;
FooBase(std::map<float,T> a_) : a(a_) {};
T func(float x1, T fallback) const;
virtual T func(float x1) const = 0;
};
class Foo: public FooBase<float> {
public:
Foo() : FooBase<float>({}) {};
float func(float x1) const;
// float func(float x1, float fallback) const;
};
void test_foo1();
void test_foo2();
#endif // __FOO_H
// foo.cpp
#include "foo.h"
template <typename T>
T FooBase<T>::func(float x1, T fallback) const {
try {
return (func(x1));
} catch(std::runtime_error&) {
return fallback;
}
};
float Foo::func(float x1) const {
return 2.0;
};
template class FooBase<float>;
void test_foo1() {
Foo foo;
float b = foo.func(1.0, 2.0);
}
void test_foo2() {
Foo foo;
float b = foo.func(1.0);
}

至关重要的是;回退"-func的版本与虚拟函数的名称相同,但签名不同,而func的单签名版本将在子类Foo中指定。

test_foo1-函数无法编译:

[  3%] Building CXX object foo.cpp.o
foo.cpp: In function ‘void test_foo1()’:
foo.cpp:20:29: error: no matching function for call to ‘Foo::func(double, double)’
20 |  float b = foo.func(1.0, 2.0);
|                             ^
foo.cpp:12:7: note: candidate: ‘virtual float Foo::func(float) const’
12 | float Foo::func(float x1) const {
|       ^~~
foo.cpp:12:7: note:   candidate expects 1 argument, 2 provided

如果我在foo.h中激活注释声明行,它会编译,但在另一个源文件中调用test_foo1时无法解析。在这种情况下,我使用了catch2-测试,当包含test_foo1时,该测试失败,而test_foo2没有问题:

[ 98%] Linking CXX executable ...
/usr/bin/ld: libFoo.so: undefined reference to `Foo::func(float, float) const'

有人能告诉我,如果我在如何实现这一点上完全错了吗?我不愿意分享构建的全部逻辑,因为重复的声明可能无论如何都是错误的方法。我希望test_foo2在另一个源文件中工作这一事实能够产生足够的信任,从而排除位于共享代码之外的问题。

基本思想是在GOF语言中;模板方法模式";带有一个没有默认值的钩子函数。特别的是,hook方法与调用它的函数同名。类具有state(a(和模板参数这一事实可能会产生影响,至少我认为我在更简单的情况下实现了这样的功能,因此我将state和模板参数包含在";最小示例";,希望这不会让事情变得太复杂。

谢谢你的帮助。

Foo::func隐藏FooBase::func。您可以使用usingFooBase::func拉入Foo的作用域:

class Foo: public FooBase<float> {
public:
Foo() : FooBase<float>({}) {};
float func(float x1) const;
using FooBase<float>::func;
};

实时演示

或者,您可以明确选择要调用的FooBase::func

void test_foo1() {
Foo foo;
float b = foo.FooBase<float>::func(1.0, 2.0);
}

相关内容

  • 没有找到相关文章

最新更新