函数指针中的协变类型

时间:2014-04-24 16:48:01

标签: c++

为什么在下面的例子中强制转换函数是错误的? 协变类型应该像这样工作吗?

#include <iostream>

struct A{};
struct B : public A{};

typedef A*(*func)();

B* b() { std::cout << "b"; return new B; }
A* a() { std::cout << "a"; return new A; }

int main(int argc, char *argv[])
{
    func fa = a;
    fa();

//  I can't do this
//  func fb = b;
//  fb();
}

4 个答案:

答案 0 :(得分:2)

它只是不受支持,即使它有意义。

在C ++ 11中,您可以轻松地在现场定义包装器:

#include <iostream>

struct A{};
struct B : public A{};

typedef A*(*func)();

B* b() { std::cout << "b"; return new B; }
A* a() { std::cout << "a"; return new A; }

int main(int argc, char *argv[])
{
    func fa = a;
    fa();

    func fb = []() -> A* { return b(); };
    fb();
}

免责声明:编译器未触及的代码。

答案 1 :(得分:2)

考虑使用std::function而不是函数指针:

#include <functional>
#include <iostream>

struct A{};
struct B : public A{};

using func = std::function<A*()>;

A* a() {std::cout << "a"; return new A;}
B* b() {std::cout << "b"; return new B;}

int main() {
    func fa = a;
    fa();

    func fb = b;
    fb();
}

Demo

答案 2 :(得分:2)

协变类型仅在类的virtual成员函数的返回类型中受支持。全局函数不支持它们。

struct A
{
   virtual A* copy() {return new A();}
};

struct B : public A
{
   virtual B* copy() {return new B();}
};

void foo()
{
   B b;
   A* ap = b.copy(); // OK
   B* bp = b.copy(); // OK
   A* ap2 = ap->copy(); // OK
   B* bp2 = ap->copy(); // NOT OK
}

您可以使用&#34; Cheers and thl建议的工作。 = Alf&#34;全球职能。

答案 3 :(得分:0)

这就是所谓的类型转换。并非每个A都是B,因此编译器无法自动执行该转换。考虑这种情况:

struct A {};
struct B : public A {};
struct C : public A {};

A* a = new A; //OK
a = new B; // B is derived from A, valid
a = new C; // C is also derived from A, valid

B* b = new B; // OK
b = new C; // error, B is not derived from C 
b = new A; // error, B might have some members that A does not have