Member Avatar for lianaconda

Hi. The idea is to create a base classed called creature with 3 derived classes called phoenix, giant, and centaur. I've already implemented all the functions, but my code still doesn't compile. I get errors that say

"error C2664: 'Phoenix::Phoenix' : cannot convert parameter 1 from 'const char [9]' to 'const Phoenix &'
1>        Reason: cannot convert from 'const char [9]' to 'const Phoenix' No constructor could take the source type, or constructor overload resolution was ambiguous"

and

"error C2664: 'Centaur::Centaur' : cannot convert parameter 1 from 'const char [9]' to 'const Centaur &'
1>        Reason: cannot convert from 'const char [9]' to 'const Centaur' No constructor could take the source type, or constructor overload resolution was ambiguous"

. I guess these errors are practically the same, but I'm not sure what they mean or how to fix my code. I thought they had to do with me not declaring a constructor for the Phoenix and Centaur classes, but I thought that all that meant was that it would inherit the constructor from the base class, which is what i want. I don't really know what's wrong with my code, can anyone help? Thanks!!

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

class Creature
{
public:
	Creature(string name);
	virtual ~Creature();
	virtual string name() const;
	virtual string move() const = 0;
	virtual bool mortal() const;

private:
	string creatureName;
};

class Phoenix : public Creature
{
public:
	virtual string move() const;
	virtual bool mortal() const;
};

class Centaur : public Creature
{
public:
	virtual string move() const;
};

class Giant : public Creature
{
public:
	Giant(string name, int heavy);
	virtual string move() const;

private:
	int weight;
};


Creature::Creature(string name):creatureName(name)
{}

Creature::~Creature()
{}

string Creature::name() const
{
	return creatureName;
}

bool Creature::mortal() const
{
	return true;
}

string Phoenix::move() const
{
	return "Fly";
}

bool Phoenix::mortal() const
{
	return false;
}

string Centaur::move() const
{
	return "trot";
}

Giant::Giant(string name, int heavy):Creature(name)
{
	weight = heavy;
}

string Giant::move() const
{
	if (weight < 20)
		return "tromp";
	else //weight is >= 20 tons
		return "lumber";
}


//From here on the code was given in the assignment, and can't be changed
void animate(const Creature* c)
{
    cout << c->name() << ", who is ";
    if (c->mortal())
        cout << "mortal";
    else
        cout << "immortal";
    cout << ", will now " << c->move() << ".\n";
}

int main()
{
    Creature* creatures[4];
    creatures[0] = new Phoenix("Squawkes");
      // Giants have a name and a weight in tons.  Giants under 20 tons
      // walk by tromping; giants weighing at least 20 tons lumber.
    creatures[1] = new Giant("Frawp", 17);
    creatures[2] = new Giant("Gridwulfa", 22);
    creatures[3] = new Centaur("Florence");

    cout << "Here are the creatures." << endl;
    for (int k = 0; k < 4; k++)
        animate(creatures[k]);

      // Clean up the creatures before exiting
    cout << "Cleaning up." << endl;
    for (int k = 0; k < 4; k++)
        delete creatures[k];
}

This is what the output's supposed to look like:

Here are the creatures.
Squawkes, who is immortal, will now fly.
Frawp, who is mortal, will now tromp.
Gridwulfa, who is mortal, will now lumber.
Florence, who is mortal, will now trot.
Cleaning up.
Destroying Squawkes the phoenix.
Destroying Frawp the giant.
Destroying Gridwulfa the giant.
Destroying Florence the centaur.

Hey, you have all the difficult bits already figured out!

There are only two problems in your code:

Firstly, when you derive a class that has a non-default constructor it does not automatically inherit to the derived class.

So when you call
creatures[3] = new Centaur("Florence");
it gives you an error because there is no constructor that takes a string argument.
So you have to define one.
The trick then is to specify that that particular constructor must call the base class constructor which takes a string argument, and not the default constructor.
This is done using the initialisation list syntax.
So the definition you are missing is:

Centaur::Centaur (string name) : Creature(name) { }

Same for Phoenix.

Now if you compile this, you will run into a second problem. Neither Centaur, Giant nor Phoenix know anything about creatureName. That's because it's declared private. If you want your derived classes to have that attribute then the qualifier you need is protected.

So here is the working code:

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

class Creature
{
public:
	Creature(string name);
	virtual ~Creature();
	virtual string name() const;
	virtual string move() const = 0;
	virtual bool mortal() const;

protected:
	string creatureName;
};

class Phoenix : public Creature
{
public:
    Phoenix (string name);
	virtual string move() const;
	virtual bool mortal() const;
};

class Centaur : public Creature
{
public:
    Centaur (string name);
	virtual string move() const;
};

class Giant : public Creature
{
public:
	Giant(string name, int heavy);
	virtual string move() const;

private:
	int weight;
};


Creature::Creature(string name):creatureName(name)
{}

Creature::~Creature()
{}

string Creature::name() const
{
	return creatureName;
}

bool Creature::mortal() const
{
	return true;
}

Phoenix::Phoenix (string name) : Creature (name)
{ }

string Phoenix::move() const
{
	return "Fly";
}

bool Phoenix::mortal() const
{
	return false;
}

Centaur::Centaur (string name) : Creature (name)
{ }

string Centaur::move() const
{
	return "trot";
}

Giant::Giant(string name, int heavy):Creature(name)
{
	weight = heavy;
}

string Giant::move() const
{
	if (weight < 20)
		return "tromp";
	else //weight is >= 20 tons
		return "lumber";
}


//From here on the code was given in the assignment, and can't be changed
void animate(const Creature* c)
{
    cout << c->name() << ", who is ";
    if (c->mortal())
        cout << "mortal";
    else
        cout << "immortal";
    cout << ", will now " << c->move() << ".\n";
}

int main()
{
    Creature* creatures[4];
    creatures[0] = new Phoenix("Squawkes");
      // Giants have a name and a weight in tons.  Giants under 20 tons
      // walk by tromping; giants weighing at least 20 tons lumber.
    creatures[1] = new Giant("Frawp", 17);
    creatures[2] = new Giant("Gridwulfa", 22);
    creatures[3] = new Centaur("Florence");

    cout << "Here are the creatures." << endl;
    for (int k = 0; k < 4; k++)
        animate(creatures[k]);

      // Clean up the creatures before exiting
    cout << "Cleaning up." << endl;
    for (int k = 0; k < 4; k++)
        delete creatures[k];
        
    cin.get();
}
Member Avatar for lianaconda

Thanks so much!!!!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.