im learning cpp and found a weird compilation error i couldnt understand why i keep getting. I simplified my code to the following as an example:
#include <iostream>
class A {
public:
static A foo()
{
A a;
return a;
}
};
class B : A
{
public:
static B boo()
{
B b;
return b;
}
};
typedef A (*function)(void);
int main() {
function f1 = A::foo;
function f2 = B::boo; //error
return 0;
}
I get the following error: "Cannot initialize a variable of type 'function' (aka 'A (*)()') with an lvalue of type 'B ()': different return type ('A' vs 'B')"
Would anyone be able to explain why it doesn't work? Since B is a child of A, B is A, so i don't understand why a function pointer from void to B isn't like a function pointer from void to A?
Any help will be appreciated, thanks!
CodePudding user response:
It is true that C allows a pointer to a child class to get converted to a pointer to the parent class (subject to certain conditions).
It is also true that C allows a reference to a child class to get converted to a reference to the parent class (also subject to certain conditions).
However, that does not mean that C allows a pointer to a function that returns a parent class to be converted to a pointer to a function that returns the child class. This is what the shown code is trying to do, and that is not allowed.
That answer your question of "why": because this is not allowed in C . As far as why, the "why"; that's mostly due to some practical considerations, but that's immaterial, that's just not allowed by the rules of C .
CodePudding user response:
Your function
claims that it should return an A
but boo
returns a B
, so:
typedef A (*A_function)();
typedef B (*B_function)();
int main() {
A_function f1 = A::foo;
B_function f2 = B::boo;
}
You could possibly solve it by returning a base class pointer from both functions:
class A {
public:
virtual ~A() = default; // for destruction via a base class pointer
static A* foo() { return new A; }
};
class B : A { // you should probably use public inheritance
public:
static A* boo() { return new B; } // creates a B but returns an A*
};
typedef A* (*function)();
int main() {
function f1 = A::foo;
function f2 = B::boo;
}
Or better, using smart pointers to not have to delete
instances manually:
#include <memory>
class A {
public:
virtual ~A() = default;
static std::unique_ptr<A> foo() { return std::make_unique<A>(); }
};
class B : public A {
public:
static std::unique_ptr<A> boo() { return std::make_unique<B>(); }
};
using function = std::unique_ptr<A>(*)();
int main() {
function f1 = A::foo;
function f2 = B::boo;
}