C++ - 希望虚拟仅作为重定向
假设我有一个模板:
template <class N, class I>
void add(N* element, std::list<N*> & container, I (N::*f)() const,
std::string successmsg, std::string exceptmsg) {
//...
}
我想调用它来获取指向派生类的基类指针的列表。
add(newAirplane, airplanes, &Airplane::getRegistration,
"Added!", "Error: Existent!");
Airplane
继承自AirplaneType
。
当然,它无法编译,N 首先定义为 AirplaneType
,然后定义为 Airplane
。
我添加了一个虚拟 getRegistration
@AirplaneType 但当然,编译器会给出 vtable 错误。
解决这个问题的正确方法是什么? AirplaneType
没有 registration
属性,我对它拥有一个不感兴趣。我还想避免 virtual getRegistration() const {return "";}
有什么好的实践建议吗?
编辑:
感谢您的回答,但仍然不起作用。我想我已经找到了剩下的问题,但没有找到它的解决方案:
void Airline::addAirplane(AirplaneType* airplane) {
add(newAirplane, airplanes, &Airplane::getRegistration,
"Added!", "Error: Existent!");
}
收到的指针类型是AirplaneType
,而不是Airplane
。
airplanes
是 AirplaneType
指针的列表。
Let's say I have a template:
template <class N, class I>
void add(N* element, std::list<N*> & container, I (N::*f)() const,
std::string successmsg, std::string exceptmsg) {
//...
}
And I want to call it for a list of Base Class pointers to a derivative class.
add(newAirplane, airplanes, &Airplane::getRegistration,
"Added!", "Error: Existent!");
Airplane
inherits from AirplaneType
.
Of course, it doesn't compile, N is first defined as AirplaneType
and then as Airplane
.
I added a virtual getRegistration
@ AirplaneType but of course, the compiler gives out a vtable error.
What's the proper way to solve this? AirplaneType
has no registration
attribute and I'm not interested in it having one. I also wanted to avoid virtual getRegistration() const {return "";}
Any suggestions for good practice?
EDIT:
Thanks for answers, but still not working. I think I have found the remaining problem, but not its solution:
void Airline::addAirplane(AirplaneType* airplane) {
add(newAirplane, airplanes, &Airplane::getRegistration,
"Added!", "Error: Existent!");
}
The type of pointer received is AirplaneType
, not Airplane
.
airplanes
is a list of AirplaneType
pointers.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
由于 C++ 不处理逆变类型,因此您需要为公共基础添加额外的模板参数。也就是说,
std::list
是与std::list
完全不同的类型,并且不能从指向派生最多的指针到派生最少的指针列表。因此,实际上您的 add 函数需要变为:You need to add an additional template parameter for the common base since C++ does not handle contravariant types. That is,
std::list<Airplane*>
is an entirely different type fromstd::list<AirplaneType*>
, and no implicit conversion can occur from the list of pointers to the most derived to the least derived.. So, effectively your add function would need to become:您需要另一个模板参数,因为您关心两个不同的类 - 指针的类型(以及您要使用它调用的成员函数)和容器的类型:
在本例中,我的
add
函数并没有真正使用container
是一个list
的事实,因此更明智的版本可能是:然后,您可以进一步抽象:
。 ..但这对于调用者来说稍微不太方便:
有什么好的实践建议吗?
不要创建原始指针的容器。
编辑:要使其与虚拟函数一起使用,我的每个选项:
输出是:
即使函数指针指向
AirplaneType::check
,而不是 <,也显示覆盖被正确调用。代码>飞机::检查。You need another template parameter, because you care about two different classes - the type of the pointer (and hence the member function you're going to call with it), and the type of the container:
In this case my
add
function doesn't really use the fact thatcontainer
is alist
, so a more sensible version might be:And then again, you could abstract further:
... but that's slightly less convenient for the caller:
Any suggestions for good practice?
Don't create containers of raw pointers.
Edit: to get this working with a virtual function, with each of my options:
Output is:
which shows that the override is correctly called even though the function pointer was taken to
AirplaneType::check
, notAirplane::check
.