tuks
tuks

Reputation: 790

C++ method inheritance with return type depending on class

Let's say I have this class:

class Food
{
public:
    Food * copy() const
    {
        return new Food(*this);
    }
    .
    .
    .
};

And I want it to be the base class for other classes which would inherit the copy method. I would have to write it manually every time:

class Cheese: public Food
{
public:
    Cheese * copy() const
    {
        return new Cheese(*this);
    }
    .
    .
    .
};

class Bread: public Food
{
public:
    Bread * copy() const
    {
        return new Bread(*this);
    }
    .
    .
    .
};

etc. How to solve that problem? I'm thinking of templates, but I'm still not sure how to use them... Here is the program I made, and it won't compile:

#include <cstring>

template <class T>

class Food
{
protected:
    double weight;
public:
    T * copy() { return new T(*this); }
    Food(){ weight = 1; }
    Food(const Food& f){ weight = f.weight; }
};

class Cheese : public Food<Cheese>
{
    char * color;
public:
    Cheese(const char * c)
    {
        color = new char[strlen(c)+1];
        strcpy(color,c);
    }
    Cheese(const Cheese& c)
    {
        weight = c.weight;
        color = new char[strlen(c.color)+1];
        strcpy(color,c.color);
    }
};

main()
{
    Cheese first("yellow");
    Cheese * second = first.copy();
}

And here are the errors:

|10|error: no matching function for call to ‘Cheese::Cheese(Food<Cheese>&)’|
|10|note: candidates are:|
|24|note: Cheese::Cheese(const Cheese&)|
|24|note:   no known conversion for argument 1 from ‘Food<Cheese>’ to ‘const Cheese&’|
|19|note: Cheese::Cheese(const char*)|
|19|note:   no known conversion for argument 1 from ‘Food<Cheese>’ to ‘const char*’|
||In member function ‘T* Food<T>::copy() [with T = Cheese]’:|
|10|warning: control reaches end of non-void function [-Wreturn-type]|

What am I doing wrong and what is the best way to accomplish this?

Upvotes: 1

Views: 180

Answers (1)

Igor Tandetnik
Igor Tandetnik

Reputation: 52461

Make it

T * copy() { return new T(*static_cast<T*>(this)); }

In Food<T>::copy, 'this' is Food<T>*, while you need a T*.

Upvotes: 3

Related Questions