Variant return type

C

C++

According to Thinking in C++
"You cannot modify the return type of a virtual function during
overriding.but there is a special case in which you can slightly
modify the return type. If you¡¯re returning a pointer or a reference to a
base class, then the overridden version of the function may
return a pointer or reference to a class derived from what the base
returns." And here's the example:

class PetFood
{
public:
virtual string foodType() const = 0;
};

class Pet
{
public:
virtual string type() const = 0;
virtual PetFood* eats() = 0;
};

class Bird : public Pet
{
public:
string type() const { return "Bird"; }
class BirdFood : public PetFood
{
public:
string foodType() const
{
return "Bird food";
}
};

// Upcast to base type:
PetFood* eats() { return &bf; }
private:
BirdFood bf;
};

class Cat : public Pet
{
public:
string type() const { return "Cat"; }
class CatFood : public PetFood
{
public:
string foodType() const { return "Birds"; }
};
// Return exact type instead:
CatFood* eats() { return &cf; }
private:
CatFood cf;
};

int main()
{
Bird b;
Cat c;
Pet* p[] = { &b, &c, };
for(int i = 0; i < sizeof p / sizeof *p; i++)
cout << p->type() << " eats "
<< p->eats()->foodType() << endl;
// Can return the exact type:
Cat::CatFood* cf = c.eats();
Bird::BirdFood* bf;
// Cannot return the exact type:
//! bf = b.eats();
// Must downcast:
bf = dynamic_cast<Bird::BirdFood*>(b.eats());
}

What annoying me is that once I get code above compiled, I get a compiler
error saying
"overriding virtual function differs from 'Pet::eats' only by return type or
calling convention" which is for "CatFood* eats() { return &cf; }"
But this differ is author's intension, How's that was flagged as an error?
 
N

Neelesh Bodas

C++ said:
What annoying me is that once I get code above compiled, I get a compiler
error saying
"overriding virtual function differs from 'Pet::eats' only by return type or
calling convention" which is for "CatFood* eats() { return &cf; }"
But this differ is author's intension, How's that was flagged as an error?

Compiles well on g++3.4.2 and also on Comeau online.
Probably your compiler might have a bug.
 
A

Alf P. Steinbach

* C++:
According to Thinking in C++
"You cannot modify the return type of a virtual function during
overriding.but there is a special case in which you can slightly
modify the return type. If you¡¯re returning a pointer or a reference to a
base class, then the overridden version of the function may
return a pointer or reference to a class derived from what the base
returns." And here's the example:

class PetFood
{
public:
virtual string foodType() const = 0;
};

class Pet
{
public:
virtual string type() const = 0;
virtual PetFood* eats() = 0;
};

class Bird : public Pet
{
public:
string type() const { return "Bird"; }
class BirdFood : public PetFood
{
public:
string foodType() const
{
return "Bird food";
}
};

// Upcast to base type:
PetFood* eats() { return &bf; }
private:
BirdFood bf;
};

class Cat : public Pet
{
public:
string type() const { return "Cat"; }
class CatFood : public PetFood
{
public:
string foodType() const { return "Birds"; }
};
// Return exact type instead:
CatFood* eats() { return &cf; }
private:
CatFood cf;
};

int main()
{
Bird b;
Cat c;
Pet* p[] = { &b, &c, };
for(int i = 0; i < sizeof p / sizeof *p; i++)
cout << p->type() << " eats "
<< p->eats()->foodType() << endl;
// Can return the exact type:
Cat::CatFood* cf = c.eats();
Bird::BirdFood* bf;
// Cannot return the exact type:
//! bf = b.eats();
// Must downcast:
bf = dynamic_cast<Bird::BirdFood*>(b.eats());
}

What annoying me is that once I get code above compiled, I get a compiler
error saying
"overriding virtual function differs from 'Pet::eats' only by return type or
calling convention" which is for "CatFood* eats() { return &cf; }"
But this differ is author's intension, How's that was flagged as an error?


It means you're using an old compiler.

FAQ item 20.8 (as the numbering is right now) describes covariant return
types, <url:
http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.8>.

Section 1.5.3 of
<url:
http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01_beta.doc.pdf>
describes a workaround for older compilers such as (presumably) yours,
as well as discussing the issues in more detail & generality.
 
D

deane_gavin

C++ said:
According to Thinking in C++
"You cannot modify the return type of a virtual function during
overriding.but there is a special case in which you can slightly
modify the return type. If you¡¯re returning a pointer or a reference to a
base class, then the overridden version of the function may
return a pointer or reference to a class derived from what the base
returns." And here's the example:

class PetFood
{
public:
virtual string foodType() const = 0;
};

class Pet
{
public:
virtual string type() const = 0;
virtual PetFood* eats() = 0;
};

class Bird : public Pet
{
public:
string type() const { return "Bird"; }
class BirdFood : public PetFood
{
public:
string foodType() const
{
return "Bird food";
}
};

// Upcast to base type:
PetFood* eats() { return &bf; }
private:
BirdFood bf;
};

class Cat : public Pet
{
public:
string type() const { return "Cat"; }
class CatFood : public PetFood
{
public:
string foodType() const { return "Birds"; }
};
// Return exact type instead:
CatFood* eats() { return &cf; }
private:
CatFood cf;
};

int main()
{
Bird b;
Cat c;
Pet* p[] = { &b, &c, };
for(int i = 0; i < sizeof p / sizeof *p; i++)
cout << p->type() << " eats "
<< p->eats()->foodType() << endl;
// Can return the exact type:
Cat::CatFood* cf = c.eats();
Bird::BirdFood* bf;
// Cannot return the exact type:
//! bf = b.eats();
// Must downcast:
bf = dynamic_cast<Bird::BirdFood*>(b.eats());
}

What annoying me is that once I get code above compiled, I get a compiler
error saying
"overriding virtual function differs from 'Pet::eats' only by return type or
calling convention" which is for "CatFood* eats() { return &cf; }"
But this differ is author's intension, How's that was flagged as an error?


What compiler are you using? Comeau online compiles your code fine if I
add

#include <iostream>
#include <string>
using namespace std;

at the beginning. If you are using an old compiler you may have the
problem described here:

http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.8

Gavin Deane
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top