C++ 使用虚函数

C++ using virtual functions

我的程序为每个客户输出一组奇怪的数字,但它没有获取每个客户的姓名。我不确定我是否正确使用了虚函数,因为这在概念上对我来说是相对较新的东西。

每个 class 都使用了 Compute_Bill() 函数,因为 Premium_Customer 使用与普通客户不同的账单计算方法。我已经注释掉了每张账单计算的费用。

main() 函数仅用于为每个人构建一个具有不同名称和呼叫次数的列表,这样程序应该会显示两种不同定价计划的示例。

这是输出:

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.

这是我的程序,从上到下依次是 Customer class、Premium Class,然后是 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 = 
// 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 = 
// 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;
}

你犯了很多小错误。你的继承基本没问题,你只需要去掉你不需要的部分:

#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 = 
// 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 = 
// 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;
}

您的代码存在未定义行为,因为您的构造函数未初始化成员字段。特别是成员 numCalls 从未被初始化,它用于方法 Compute_Bill.

的结果

像 valgrind 这样的工具指出了这样的错误:在你的代码中,valgrind 说

by 0x401C55: main (file.cpp:157)
Conditional jump or move depends on uninitialised value(s)

事实上在你的方法中setCall,你应该定义

numCalls = aCall;

而不是

aCall = numCalls;

它没有影响,因为它确实影响了一个参数。