[英]C++ pointer to member of derived class
我不明白这里发生了什么。 我有一个包含字段a
的类Base
。 现在我创建了一个扩展 Base 的Derived
类。 我还有一个模板函数,它通过传递指向成员的模板参数来打印我们想要的字段。
#include <iostream>
class Base {
public:
Base(double a):a{a} {}
double a;
};
class Derived : public Base {
public:
Derived(double a) : Base(a) {}
};
template<double (Derived::*p)>
void print(Derived d) {
std::cout << d.*p;
}
int main() {
Derived d {10.0};
print<&Derived::a>(d);
}
问题是它不起作用,但如果我只使用基类:
template<double (Base::*p)>
void print(Base b) {
std::cout << b.*p;
}
int main() {
Base b {10.0};
print<&Base::a>(b);
}
它按预期工作并打印10.0
。 我怎样才能让它与子类一起工作?
编译器说:
test.cpp:15:6: note: template argument deduction/substitution failed:
test.cpp:21:23: error: could not convert template argument ‘&Base::a’ from ‘double Base::*’ to ‘double Derived::*’
print<&Derived::a>(d);
正如其他人解释的原因,我将解释解决方案:
template<typename T, double (T::*p)>
void print(T d) {
std::cout << d.*p;
}
int main() {
Derived d {10.0};
print<Base, &Base::a>(d);
}
https://gcc.godbolt.org/z/pM762f
我敢肯定这不是您所希望的,但总比重载每个版本要好。 但我认为最好找到解决问题的更好方法,因为我知道这里的代码不是您实际面临的问题,因为您可以传递 double 本身而不是成员指针。
因此,请尝试在您的代码上下文中解决问题,而不是通过这种方式。 以下是一些可能会解决您实际问题的想法(如果您有的话):
enum
std::map
如果不是太多constexpr
,因此您也可以在模板中使用它们)print
功能移到基类甚至派生类中以及许多其他解决方案,其中大多数可能对您没有帮助(因为我不知道您的代码的上下文)。
这将是仅编译器消息就具有人们必须想要的所有解释的示例之一:
<source>: In function 'int main()':
<source>:21:23: error: no matching function for call to 'print<&Base::a>(Derived&)'
21 | print<&Derived::a>(d);
| ^
<source>:15:6: note: candidate: 'template<double Derived::* p> void print(Derived)'
15 | void print(Derived d) {
| ^~~~~
<source>:15:6: note: template argument deduction/substitution failed:
<source>:21:23: error: '&Base::a' is not a valid template argument for type 'double Derived::*'
21 | print<&Derived::a>(d);
| ^
<source>:21:23: note: because it is a member of 'Base'
Compiler returned: 1
回答评论中的一个问题:模板参数不能隐式转换为指向 base 成员的指针,而static_cast
也无济于事,因为对于作为成员指针的模板非类型参数,必须以&C::m
的形式编写(请参阅https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_members )
不是那么明显,但是指向a
的成员指针的类型是double Base::*
,无论它指向Derived
对象还是Base
对象中的a
。 您的方法只接受一个Derived
参数,并且只接受一个指向Derived
中的成员的指针作为模板参数。 如果你想允许不同的组合,你可以写更多的重载。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.