Cannot initialize a variable of type ‘pet *’ with an rvalue of type ‘dog *’ [closed]

I’m creating a “pet shop system” for an assignment for school. I’ll leave the full instructions below my code, but the summary is:

I’m supposed to be using concepts like pointers, header files, OOP, and inheritance, to be able to do this. Basically, the system will take a pet, either a dog or a cat, and display its name and licensing fee (which is determined by the weight of the pet – a dog is $2/lbs and a cat is $1.50/lb).

In my main() function, I’m trying to create a vector of pointers to the pet class, and I’m asked to create 3 instances of pets; two dogs, one cat. I’m trying to store each of their pointers in the vector.

The problem is, I’m creating them using their dog and cat classes, but I want them to be stored as pet pointers. I’m getting this error when trying to create the dog instance, for example:

Cannot initialize a variable of type ‘pet *’ with an rvalue of type ‘dog *’

I’ve changed pet* to dog* but all that did was give me a different error message:

No matching member function for call to ‘push_back’

I don’t know how to solve this so that I can specify which animal the pet is, but store them as pointers in my pvec vector.

Here are the minimized versions of my files (the parts I’m focused on), as well as my instructions prompted by the assignment:

main.cpp:

#include <iostream>
#include <string>
#include <vector>
#include "pet.hpp"
#include "dog.hpp"
#include "cat.hpp"

using namespace std;

int main() {
    vector<pet*> pvec; //creates a list of pointers to pets

    //creating 3 pets to test program, two dogs and one cat
    pet* bob = new dog("Bob", 65, 0.0); //uses constructors from dog class, setting initial price to 0
    pvec.push_back(bob); //adds bob to the vector
    pet* stan = new dog("Stan", 37, 0.0);
    pvec.push_back(stan);
    pet* tom = new cat("Tom", 12, 0.0);
    pvec.push_back(tom);

pet.cpp, which reflects the pet header file

pet.hpp:

#ifndef pet_hpp
#define pet_hpp

#include <string>

using namespace std;

class pet {
public:
    pet();
    pet(string name, int weight, float price);
    void SetName(string name) {
        pet_name = name;
    }
    string GetName() {
        return pet_name;
    }
    void SetWeight(int weight) {
        pet_weight = weight;
    }
    string GetWeight() {
        return pet_name;
    }
    void SetPrice(float price) {
        pet_price = price;
    }
    static float GetPrice() {
        return pet_price;
    };
private:
    string pet_name;
    int pet_weight;
    static float pet_price;
};

#endif //pet_hpp

dog.cpp, which reflects dog header

dog.hpp:

#ifndef dog_hpp
#define dog_hpp

#include <string>
#include <iostream>
#include "pet.hpp"

using namespace std;

class dog : public pet {
public:
    dog();
    dog(string name, int weight, float price);
    void SetName(string name) {
        dog_name = name;
    }
    string GetName() {
        return dog_name;
    }
    void SetWeight(int weight) {
        dog_weight = weight;
    }
    int GetWeight() {
        return dog_weight;
    }
    void SetPrice(float price) {
        dog_price = price;
    }
    float GetPrice() {
        return dog_price;
    }
    static float licensing_rate;
private:
    string dog_name;
    int dog_weight;
    float dog_price;
};

float dog::licensing_rate = 2.0; //sets the rate for dogs at $2 a pound

#endif //dog_hpp

cat.cpp, which reflects cat header

cat.hpp:

#ifndef cat_hpp
#define cat_hpp

#include <string>
#include "pet.hpp"

using namespace std;

class cat : public pet {
public:
    cat();
    cat(string name, int weight, float price);
    void SetName(string name) {
        cat_name = name;
    }
    string GetName() {
        return cat_name;
    }
    void SetWeight(int weight) {
        cat_weight = weight;
    }
    int GetWeight() {
        return cat_weight;
    }
    void SetPrice(float price) {
        cat_price = price;
    }
    float GetPrice() {
        return cat_price;
    }
    static float licensing_rate;
private:
    string cat_name;
    int cat_weight;
    float cat_price = cat_weight;
};

float cat::licensing_rate = 1.50;

#endif //cat_hpp

Assignment Instructions:

A pet shop needs to keep track of its pets which include dogs and cats. Each type of pet (dog,
cat) has a monthly licensing rate that is ‘per pound’ of body weight for each pet. The shop wants a system to keep track of their pets and to calculate the total amount they pay on licensing fees each month.

You need to design and build such a system. Your main function should have a loop to calculate the total fee, like this:

float total_fee = 0.0;
for (int i = 0; i < pvec.size(); i++)
{
cout << pvec[i]->GetName() << ' ' << pvec[i]->CalculateFee() << endl;
total_fee = total_fee + pvec[i]->CalculateFee();
}
cout << "total licensing fee = " << total_fee << endl;

where pvec is a C++ vector of Pet pointers. The function CalculateFee should be a virtual function and Pet should be an abstract base class. The licensing rate should probably be modeled as a static class variable for each type of pet. Organize your classes in an inheritance hierarchy to reuse as much code as possible.

To test the system you can create three pets in the main function:

  1. a 65 pound dog named Bob,
  2. a 37 pound dog named Stan,
  3. a 12 pound cat named Tom.

The licensing rate for dogs can be set to $2/pound and that for cats can be $1.50/pound.

The output should then be:

Bob 130
Stan 74
Tom 18
total licensing fee = 222

  • 3

    Unrelated, but you may be interested in Why is “using namespace std;” considered bad practice?. That’s particularly evil in a header file

    – 

  • 1

    Can you reduce your code to a minimal reproducible example?

    – 

  • 1

    Another thing to consider: Make it as easy as possible for people to help you. I know it’s just a matter of copying each and every code snippet into my environment and I’ll probably see the problem. Sometimes I go through that to help, now I don’t. It’d be so much quicker if you made a minimal reproducible example.

    – 




  • 4

    Why is pet.hpp including dog.cpp? Not only should the base class avoid knowing about the derived class, but #include anything.cpp is always the wrong approach.

    – 




  • 1

    @comingundone links to external sources is discouraged, as links break over time. StackOverflow posts should be as self contained as possible. Just strip out all of the irrelevant code that is not necessary to demonstrate the problem, hence the minimal portion of a minimal reproducible example

    – 




You misunderstand how inheritance works. The variables and functions you provide in pet should NOT be duplicated in cat and dog. They will automatically inherit that behavior. The only things you need in cat and dog are the things that are unique to them — in this case, the computation of the licensing fee. In addition, your code for GetWeight and SetWeight were trying to fetch the name — a cut and paste error. Also, you were using the symbol pet_hpp as a protector in dog.hpp and cat.hpp, which means those files were never being included. That’s why I use #pragma once for this purpose.

This code works.

pet.hpp:

#ifndef pet_hpp
#define pet_hpp

#include <string>

using namespace std;

class pet {
public:
    pet(string name, int weight, float price)
        : pet_name(name)
        , pet_weight(weight)
        , pet_price(price)
    {
    }
    void SetName(string name) {
        pet_name = name;
    }
    string GetName() {
        return pet_name;
    }
    void SetWeight(int weight) {
        pet_weight = weight;
    }
    int GetWeight() {
        return pet_weight;
    }
    void SetPrice(float price) {
        pet_price = price;
    }
    float GetPrice() {
        return pet_price;
    };

    virtual float CalculateFee() = 0;
private:
    string pet_name;
    int pet_weight;
    float pet_price;
};

#endif //pet_hpp

dog.hpp:

#ifndef dog_hpp
#define dog_hpp

#include <string>
#include "pet.hpp"

using namespace std;

class dog : public pet {
public:
    dog(string name, int weight, float price)
        : pet(name, weight, price)
    {}
    virtual float CalculateFee()
    {
        return licensing_rate * GetWeight();
    }
    static float licensing_rate;
};

float dog::licensing_rate = 2.0; //sets the rate for dogs at $2 a pound

#endif

cat.hpp:

#ifndef cat_hpp
#define cat_hpp

#include <string>
#include "pet.hpp"

using namespace std;

class cat : public pet {
public:
    cat(string name, int weight, float price)
        : pet(name, weight, price)
    {}
    virtual float CalculateFee()
    {
        return licensing_rate * GetWeight();
    }
    static float licensing_rate;
};

float cat::licensing_rate = 1.50;

#endif

main.cpp:

#include <iostream>
#include <string>
#include <vector>
#include "pet.hpp"
#include "dog.hpp"
#include "cat.hpp"

using namespace std;

int main() {
    vector<pet*> pvec; //creates a list of pointers to pets

    //creating 3 pets to test program, two dogs and one cat
    pet* bob = new dog("Bob", 65, 0.0f); 
    pvec.push_back(bob); //adds bob to the vector
    pet* stan = new dog("Stan", 37, 0.0f);
    pvec.push_back(stan);
    pet* tom = new cat("Tom", 12, 0.0f);
    pvec.push_back(tom);

    float total_fee = 0.0;
    for (int i = 0; i < pvec.size(); i++)
    {
        cout << pvec[i]->GetName() << ' ' << pvec[i]->CalculateFee() << endl;
        total_fee = total_fee + pvec[i]->CalculateFee();
    }
    cout << "total licensing fee = " << total_fee << endl;
}

Output:

Bob 130
Stan 74
Tom 18
total licensing fee = 222

In some places, you are doing more work than you need to. Part of the assignment, for instance, is to, “Organize your classes in an inheritance hierarchy to reuse as much code as possible.” You should be able to do that with pet names and weights. Do they need to be repeated in class dog and class cat? Do the set and get functions need to be repeated? Is there a way to use inheritance to avoid the repetition?

Another place where you are working too hard is price. You have created a member variable, a set function, and a get function to deal with price. You even added price to the constructors. But it looks like you intend that to be a synonym for licensing_rate, which is already being stored as a “static class variable for each type of pet.” In most classes, you do not initialize static variables in the constructor (although you can if it is appropriate). If you want to write set and get functions for licensing_rate, they should be static functions (to go along with the static variables). Think about which classes need to have those functions. Why, for instance, would class pet have a licensing_rate, unless there were some overall rate that applied to all pets.

Be sure to add a virtual destructor to class pet: virtual ~pet() = default;. Otherwise, you will not be able to delete cat and dog objects using the pointers that are stored in pvec. And don’t forget to do that. At the end of function main, you should run a loop to delete the objects that are pointed to by the pointers in pvec.

There are some additional fixes you might want to make. Get functions should be marked const (after the parameter list), and so on. The biggest need, however, is to write function CalculateFee. According to the assignment, it “should be a virtual function and Pet should be an abstract base class.” Think about how to code that.

Leave a Comment