模板转换为超类
Template cast to super class
我希望能够将类I的对象作为参数的函数传递给FD构造函数::
class D {}; class I: public D {};
FD(std::function<void(D*)> f): _f(f) {}
void test(I*) { std::cout << "Success" << std::endl; }
FD fd(test); fd.call();
正如我一直在研究的那样,我应该实现类型转换,但我不知道一个干净的方法,也没有找到适用于我的案例的解决类型转换的答案。这是完整的代码:
#include <functional>
#include <iostream>
class D {}; class I: public D {};
class FD {
protected:
std::function<void(D*)> _f;
public:
explicit FD(std::function<void(D*)> f): _f(f) {}
void call() { _f(0); }
};
void test(I*) { std::cout << "Success" << std::endl; }
int main () {
FD fd(test); fd.call();
}
我得到:
test.cpp: In function ‘int main()’:
test.cpp:17:13: error: no matching function for call to ‘FD::FD(void (&)(I*))’
FD fd(test); fd.call();
^
test.cpp:10:14: note: candidate: FD::FD(std::function<void(D*)>)
explicit FD(std::function<void(D*)> f): _f(f) {}
^~
test.cpp:10:14: note: no known conversion for argument 1 from ‘void(I*)’ to ‘std::function<void(D*)>’
我也尝试过使用int和double:
#include <functional>
#include <iostream>
class FD {
protected:
std::function<void(double)> _f;
public:
explicit FD(std::function<void(double)> f): _f(f) {}
void call() { _f(0); }
};
void test(int v) { std::cout << "Success" << std::endl; }
int main () {
FD fd(test); fd.call();
}
带输出:
Success
可以用极其痛苦的技术细节来解释编译错误的原因,以及为什么你不能在C++中做你想做的事情,但如果你考虑一个非常简单的思想实验,也许这个根本原因会很清楚:
std::function<void(D*)> f;
您肯定知道,可以使用指向D
的任何子类的指针来调用这个可调用对象。您可能有另一个名为J
的类,它也继承自D,因此这是完全可以接受的:
class J : public D {};
J j;
f(&j);
但您尝试在这里使用指向仅以I *
为参数的函数的指针来构造std::function
:
void test(I*)
如果您试图执行的操作是可能的,那么这意味着可以通过std::function<void (D*)> object
使用指向J
而不是I
的指针来调用此test()
函数。失败当然,这在C++中是不允许的。如果两个类之间的唯一关系是它们都有相同的父类,那么您就无法将指向其中一个类的指针转换为指向另一个的指针。C++不能以这种方式工作。
第二个例子int
和double
工作的原因是int
和double
可以相互转换。对于指向两个随机类的指针,情况并非如此。只有在某些定义明确的情况下,指向类的指针才能转换为指向不同类的指针。C++中不允许您想要什么。
这里唯一可能发生的是test
((函数,它将D *
作为参数,交叉手指并尝试将其dynamic_cast
I *
(假设D
满足动态可浇注类的要求(。然后,您将不得不决定当转换失败时会发生什么。
当然,您可以这样执行强制转换:FD fd(reinterpret_cast<void(*)(D*)>(test));
,但这是UB。
错误很明显——不能将D*
隐式转换为I*
。这违反了多态性。
您确定没有混淆I
和D
吗?
UPD:
我认为否决这个帖子意味着它不清楚。我将尝试解释:
想象一下:
class D
{
public:
void (*ok)() = +[] { std::cout << "OK"; };
};
class I: public D
{
public:
void (*not_ok)() = ok;
};
CCD_ 23可以从CCD_ 24实例访问,而CCD_。现在您想调用函数,将指针指向I
。但这意味着您的函数可以调用not_ok()
,这对于指向D
:的指针无效
void test(I* i)
{
i->ok();
i->not_ok();
}
使用原始指针,您可以尝试以下操作:
class FD {
protected:
std::function<void(D*)> _f;
public:
explicit FD(void(*f)(I*)) : _f(reinterpret_cast<void(*)(D*)>(f))
{
}
void call() { _f(new I); }
};
它将打印OK。但如果你用new D
替换new I
,它将在not_ok()
调用时失败
这就是为什么C++不允许隐式地强制转换指针(而您仍然可以隐式地将int强制转换为double(。
即使你想"破解"你的代码,C++也没有全局类型转换规则。此外,您无法从std::函数中获取原始指针,因此,没有办法做到这一点。
- 模板转换为超类
- 模板类转换问题 - 无法推断调用的函数
- 将QOpenGLWidget子类转换为使用Metal而不是OpenGL的子类是否可行?
- 我的超类中的模板问题与结构定义
- C++将派生类转换为基类时'object slicing'期间发生的情况
- 将模板类转换为标头和 cpp 文件
- 创建子类的多个实例,其中只有一个超类实例
- 给定一个指向对象的超类指针,如何获取对象的大小?
- 将调用类转换为库本身后,库头文件上没有这样的文件
- 将 void* 强制转换为多个继承类的超类不会调用正确的方法
- 无法将超类强制转换为子类
- 将子类列表转换为超类列表
- 向上转换到超类或接口
- 关于在强制转换为子类的超类时调用其重写方法
- 在 c++ 中将多维数组强制转换为其超类的多维数组
- 将 std::unique_ptr 转换为 std::unique_ptr 转换为超类的正确方法是什么?
- 当对象不是动态分配的(不是指针)时,是否可以从超类对象转换到子类
- 如何在向方法传递超类时防止自动下转换
- 在没有数据重复的情况下强制转换/实例化/转换为子类/超类
- 为什么我不能将超类引用强制转换为同时扩展另一个超类的子类?