指向派生类成员的C ++指针

时间:2019-12-13 17:57:47

标签: c++ templates pointer-to-member

我不明白这里发生了什么。我有一个类counterexample found,其中包含一个字段-std=c11。现在,我创建一个扩展Base的Base类。我还有一个模板函数,该函数通过传递指向成员的模板参数来打印我们想要的字段。

a

问题是它不起作用,但是如果我仅使用基类:

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);
}

3 个答案:

答案 0 :(得分:0)

当仅编译器消息具有所有必须explanations的情况时,这就是示例之一:

year : Sequelize.col("episode.year")

回答评论中的问题:模板参数不能隐式转换为指向base中成员的指针,<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 则无济于事,因为对于指向成员的成员的模板非类型参数,必须以static_cast 的形式写(请参见https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_members

答案 1 :(得分:0)

不是很明显,但是指向a的成员指针的类型是double Base::*,无论它指向a对象还是指向Derived的对象。 Base个对象。您的方法仅接受Derived参数,并且仅将指向Derived中成员的指针作为模板参数。如果要允许不同的组合,则可以编写更多的重载。

答案 2 :(得分:0)

正如其他人解释了原因一样,我将解释解决方案:

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

我确定这不是您希望的,但是比重载每个版本要好。但是我认为最好是找到解决问题的更好方法,因为我知道这里的代码并不是您实际上要面对的问题,因为您可以传递双精度本身而不是成员指针。

因此,请尝试使用这种方式在代码上下文中解决问题。以下是一些可能解决您实际问题的想法(如果有的话):

  • 使用enum s
  • 考虑一下std::map是否太多
  • 您可以使用lambda(现在为constexpr,因此您也可以在模板中使用它们)
  • 考虑将print函数移至基类甚至派生类
  • 使用高阶函数(本质上是太多的lambda:D)而不是整个面向对象的解决方案。

和许多其他解决方案,其中大多数可能对您没有帮助(因为我不知道您的代码的上下文)。

相关问题