Yoyokolo Yoyokolo - 2 months ago 9
C++ Question

C++ using virtual functions

My program is outputting a strange set of numbers for each customer, and its not getting each customers' names. I'm not sure if I'm using the virtual functions correctly, as this is something relatively new to me conceptually.

The Compute_Bill() function is used in each class, because the Premium_Customer is using a different calculation for their bills than the normal Customer. I have commented out the cost for the calculations for each bill.

The main() function is just for building a list with different names and number of calls for each person, that way the program is supposed to show examples of the two different pricing plans.

Here is the output:


Customer owes 10 dollars.

Customer owes 20.4 dollars.

Customer owes -7.02934e+114 dollars.

Customer owes 20.4 dollars.

Customer owes 10 dollars.

Customer owes 20.4 dollars.

Customer owes 10 dollars.

Customer owes 20.4 dollars.

Customer owes 10 dollars.

Customer owes 20.4 dollars.

Customer owes 10 dollars.

Customer owes 20.4 dollars.

Customer owes 10 dollars.

Customer owes 20.4 dollars.

Customer owes 10 dollars.

Customer owes 20.4 dollars.

Customer owes 10 dollars.

Customer owes 1.24244e+150 dollars.


And here is my program, from top to bottom it starts with Customer class, then Premium Class, and then the main:

#include <iostream>

using namespace std;

// CUSTOMER CLASS
class Customer
{
private:
double numCalls;
string name;
const double MONTH_FEE = 10;
const double PER_CALL = .5;

protected:
double bill;

public:
Customer();
Customer(string aName, double aCalls);
virtual double Compute_Bill();
string getName();
void setName(string aName);
double getCalls();
void setCalls(double aCalls);
};

Customer::Customer()
{
}

Customer::Customer(string aName, double aCalls)
{
aName = "";
aCalls = 0;
}

string Customer::getName()
{
return name;
}

void Customer::setName(string aName)
{
aName = name;
}

double Customer::getCalls()
{
return numCalls;
}

void Customer::setCalls(double aCalls)
{
aCalls = numCalls;
}

// Computing the bill for the Customer, uses
// bill = monthlyfee + (percallrate * numcalls)
// monthly fee = $10
// per call charge = .50
double Customer::Compute_Bill()
{
bill = MONTH_FEE + (PER_CALL * numCalls);
return bill;
}


// PREMIUM_CUSTOMER CLASS
class Premium_Customer : public Customer
{
private:
double numCalls;
string name;
const double MONTH_FEE = 20;
const double PER_CALL = .05;
const double PER_MINUTE = .1;
const double NUM_MINS = 4;

protected:
double bill;

public:
Premium_Customer();
Premium_Customer(string aName, double aCalls);
virtual double Compute_Bill();
string getName();
void setName(string aName);
double getCalls();
void setCalls(double aCalls);
};

Premium_Customer::Premium_Customer()
{
}

Premium_Customer::Premium_Customer(string aName, double aCalls)
{
aName = "";
aCalls = 0;
}

string Premium_Customer::getName()
{
return name;
}

void Premium_Customer::setName(string aName)
{
aName = name;
}

double Premium_Customer::getCalls()
{
return numCalls;
}

void Premium_Customer::setCalls(double aCalls)
{
aCalls = numCalls;
}

// Computing the bill for the Premium_Customer, uses
// bill = monthlyfee + (percallrate * numcalls) + (permin_callrate * nummins)
// monthly fee = $20
// per call charge = .05
// per minute call rate = .10
// nummins = 4
double Premium_Customer::Compute_Bill()
{
bill = MONTH_FEE + (PER_CALL * numCalls) + (PER_MINUTE * NUM_MINS);
return bill;
}

// MAIN CLASS
int main () {
Customer* list[18] ;
list[0] = new Customer("John Dough", 20);
list[1] = new Premium_Customer("Bob Dough", 20);
list[2] = new Customer("Tim Dough", 30);
list[3] = new Premium_Customer("Jane Dough", 30);
list[4] = new Customer("Bill Dough", 40);
list[5] = new Premium_Customer("Tom Dough", 40);
list[6] = new Customer("Jim Dough", 50);
list[7] = new Premium_Customer("Kane Dough", 50);
list[8] = new Customer("Hon Dough", 60);
list[9] = new Premium_Customer("Jill Dough", 60);
list[10] = new Customer("Mary Dough", 70);
list[11] = new Premium_Customer("Un Dough", 70);
list[12] = new Customer("Sarah Dough", 80);
list[13] = new Premium_Customer("Liz Dough", 80);
list[14] = new Customer("Will Dough", 90);
list[15] = new Premium_Customer("Mike Dough", 90);
list[16] = new Customer("Brian Dough", 100);
list[17] = new Premium_Customer("Kurt Dough", 100);
for(int i=0; i<18; i++) {
cout << "Customer " << list[i]->getName() << " owes "
<< list[i]->Compute_Bill() << " dollars." << endl;
}
// delete all the customers
return 1;
}

Answer

You had a lot of small mistakes. Your inheritance was basically fine, you just need to remove the parts you don't need:

#include <iostream>
#include <string>

using namespace std;

// CUSTOMER CLASS
class Customer
{
private:
    double numCalls;
    string name;
    const double MONTH_FEE = 10;
    const double PER_CALL = .5;

protected:
    double bill;

public:
    Customer();
    Customer(const string& aName, double aCalls);
    virtual double Compute_Bill();
    string getName() const;
    void setName(const string& aName);
    double getCalls() const;
    void setCalls(double aCalls);
};

Customer::Customer()
{
}

Customer::Customer(const string& aName, double aCalls)
{
    setName(aName);
    setCalls(aCalls);
}

string Customer::getName() const
{
    return name;
}

void Customer::setName(const string& aName)
{
    // you had this mixed up
    name = aName;
}

double Customer::getCalls() const
{
    return numCalls;
}

void Customer::setCalls(double aCalls)
{
    // this was mixed up too
    numCalls = aCalls;
}

// Computing the bill for the Customer, uses
// bill = monthlyfee + (percallrate * numcalls)
// monthly fee = $10
// per call charge = .50
double Customer::Compute_Bill()
{
    bill = MONTH_FEE + (PER_CALL * numCalls);
    return bill;
}


// PREMIUM_CUSTOMER CLASS
class Premium_Customer : public Customer
{
private:
    const double MONTH_FEE = 20;
    const double PER_CALL = .05;
    const double PER_MINUTE = .1;
    const double NUM_MINS = 4;

public:
    Premium_Customer();
    Premium_Customer(const string& aName, double aCalls);
    virtual double Compute_Bill();
    // the other methods are already inherited, no need to implement them again... 
};

Premium_Customer::Premium_Customer()
{
}

// no special logic here, just delegate to your base class constructor
Premium_Customer::Premium_Customer(const string& aName, double aCalls) : Customer(aName, aCalls)
{   
}

// Computing the bill for the Premium_Customer, uses
// bill = monthlyfee + (percallrate * numcalls) + (permin_callrate *   nummins)
// monthly fee = $20
// per call charge = .05
// per minute call rate = .10
// nummins = 4
double Premium_Customer::Compute_Bill()
{
    // no direct access to private customer variables here, used getCalls method instead
    bill = MONTH_FEE + (PER_CALL * getCalls()) + (PER_MINUTE * NUM_MINS);
    return bill;
}

// MAIN CLASS
int main() {
    Customer* list[18];
    list[0] = new Customer("John Dough", 20);
    list[1] = new Premium_Customer("Bob Dough", 20);
    list[2] = new Customer("Tim Dough", 30);
    list[3] = new Premium_Customer("Jane Dough", 30);
    list[4] = new Customer("Bill Dough", 40);
    list[5] = new Premium_Customer("Tom Dough", 40);
    list[6] = new Customer("Jim Dough", 50);
    list[7] = new Premium_Customer("Kane Dough", 50);
    list[8] = new Customer("Hon Dough", 60);
    list[9] = new Premium_Customer("Jill Dough", 60);
    list[10] = new Customer("Mary Dough", 70);
    list[11] = new Premium_Customer("Un Dough", 70);
    list[12] = new Customer("Sarah Dough", 80);
    list[13] = new Premium_Customer("Liz Dough", 80);
    list[14] = new Customer("Will Dough", 90);
    list[15] = new Premium_Customer("Mike Dough", 90);
    list[16] = new Customer("Brian Dough", 100);
    list[17] = new Premium_Customer("Kurt Dough", 100);

    for (int i = 0; i<18; i++) {
        cout << "Customer " << list[i]->getName() << " owes " << list[i]->Compute_Bill() << " dollars." << endl;
    }

    // delete all the customers
    return 0;
}
Comments