美文网首页C++ Primer Plus习题及答案
C++ Primer Plus习题及答案-第十章

C++ Primer Plus习题及答案-第十章

作者: 艰默 | 来源:发表于2022-10-07 09:06 被阅读0次

    习题选自:C++ Primer Plus(第六版)
    内容仅供参考,如有错误,欢迎指正 !

    • 构造函数是一种特殊的类成员函数,在创建类对象时被调用。
    • 构造函数的名称和类名相同,但通过函数重载,可创建多个同名的构造函数,条件是每个函数的特征标(参数列表)不同。
    • 每个成员函数(包括构造函数和析构函数)都有一个this指针,this指针指向调用对象,如果方法需要引用整个调用对象,则可以使用表达式*this。在函数的括号后面使用限定符将this限定为const,这样将不能使用this来修改对象的值。

    复习题

    1.什么是类?

    类是用户定义的类型的定义。类声明指定了数据将如何存储,同时提供了访问和操作这些数据的方法。

    2.类如何实现抽象、封装和数据隐藏?

    用户可以根据类的公有接口对类对象执行的操作,这是抽象。类的数据成员可以是私有的(默认值),这意味着只能通过类成员函数来对数据进行访问,这是数据隐藏。实现的具体细节(如数据的表示和方法的代码)都是隐藏的,这是封装。

    3.对象和类之间的关系是什么?

    类定义了一种类型,包括如何使用它。对象是一个变量或其他的数据对象(如new生成的),并根据类定义被创建和使用。类和对象之间的关系同标准类型与其变量之间的关系。

    4.除了是函数之外,类函数成员与类数据成员之间的区别是什么?

    如果创建给定类的多个对象,则每个对象都有其自己的数据内存空间;但所有的对象都使用同一组成员函数(通常,这个方法是公有的,而数据是私有的,但这只是策略方面的问题,而不是对类的要求)

    5.定义一个类来表示银行账户、数据成员包括储户姓名、帐号(使用字符串)和存款。成员函数执行如下操作:
    • 创建一个对象并将其初始化。
    • 显示储户姓名、帐号和存款。
    • 存入参数指定的存款。
    • 取出参数指定的款项。
    请提供类声明,而不用给出方法实现。(编程练习1将要求编写实现)
    
    #ifndef BANKACCOUNT_H
    #define BANKACCOUNT_H
    #include <string>
    
    using namespace std;
    
    class BankAccount
    {
    private:
        std::string name_str;
        std::string accountNum_str;
        double balance;
    
    public:
        BankAccount(const string &name, const string &accountNum, double bal = 0.0);
        void show();
        void deposit(double cash);
        void withdraw(double cash);
    };
    
    #endif
    
    
    6.类构造函数在何时被调用?类析构函数呢?

    在创建类对象或显示调用构造函数时,类的构造函数被调用。当函数过期时,析构函数被调用。

    7.给出复习题5中的银行账户的构造函数的代码。
    #include "BankAccount.h"
    #include <iostream>
    using namespace std;
    
    BankAccount::BankAccount(const string &name, const string &accountNum, double bal)
    {
        name_str = name;
        accountNum_str = accountNum;
        balance = bal;
    }
    
    void BankAccount::show()
    {
        cout << "Account Name : " << name_str << endl;
        cout << "Account Number : " << accountNum_str << endl;
        cout << "Account Balance : " << balance << endl;
    }
    
    void BankAccount::withdraw(double cash)
    {
        balance -= cash;
    }
    
    void BankAccount::deposit(double cash)
    {
        balance += cash;
    }
    
    
    8.什么是默认构造函数,拥有默认构造函数有何好处?

    默认构造函数是没有参数或所有参数都有默认值的构造函数。拥有默认构造函数后,可以声明对象,而不初始化它,即使已经定义了初始化构造函数。它还使得能够声明数组。

    9.修改Stock类的定义(stock20.h中的版本),使之包含返回各个数据成员值的成员函数。注意:返回公司名的成员函数不应该为修改数组提供便利,也就是说,不能简单的返回string引用。

    原stock20.h的版本:

    //Listing 10.7 stock20.h
    // stock20.h -- augmented version
    #ifndef STOCK20_H_
    #define STOCK20_H_
    #include <string>
    class Stock
    {
    private:
        std::string company;
        int shares;
        double share_val;
        double total_val;
        void set_tot() { total_val = shares * share_val; }
    
    public:
        Stock(); // default constructor
        Stock(const std::string &co, long n = 0, double pr = 0.0);
        ~Stock(); // do-nothing destructor
        void buy(long num, double price);
        void sell(long num, double price);
        void update(double price);
        void show() const;
        const Stock &topval(const Stock &s) const;
    };
    #endif
    

    修改后:

    #ifndef STOCK20_H_
    #define STOCK20_H_
    #include <string>
    class Stock
    {
    private:
        std::string company;
        int shares;
        double share_val;
        double total_val;
        void set_tot() { total_val = shares * share_val; }
    
    public:
        Stock();
        Stock(const std::string &co, long n = 0, double pr = 0.0);
        ~Stock();
        void buy(long num, double price);
        void sell(long num, double price);
        void update(double price);
        void show() const;
        const Stock &topval(const Stock &s) const;
        int shares() const { return shares; }
        double shareVal() const { return share_val; }
        double totalVal() const { return total_val; }
        const std::string &comp_name() const { return company; }
    };
    #endif
    
    10.this和*this是什么?

    this指针是类方法可以使用的指针,它指向用于调用方法的对象。因此,this是对象的地址,*this是对象本身。

    编程练习

    1.为复习题5描述的类提供方法定义,并编写一个小程序来演示所有的特性。

    BankAccount.h:

    
    #ifndef BANKACCOUNT_H
    #define BANKACCOUNT_H
    #include <string>
    
    using namespace std;
    
    class BankAccount
    {
    private:
        std::string name_str;
        std::string accountNum_str;
        double balance;
    
    public:
        BankAccount(const string &name, const string &accountNum, double bal = 0.0);
        void show();
        void deposit(double cash);
        void withdraw(double cash);
    };
    
    #endif
    
    

    BankAccount.cpp:

    #include "BankAccount.h"
    #include <iostream>
    using namespace std;
    
    BankAccount::BankAccount(const string &name, const string &accountNum, double bal)
    {
        name_str = name;
        accountNum_str = accountNum;
        balance = bal;
    }
    
    void BankAccount::show()
    {
        cout << "Account Name : " << name_str << endl;
        cout << "Account Number : " << accountNum_str << endl;
        cout << "Account Balance : " << balance << endl;
    }
    
    void BankAccount::withdraw(double cash)
    {
        balance -= cash;
    }
    
    void BankAccount::deposit(double cash)
    {
        balance += cash;
    }
    
    

    main.cpp:

    #include "BankAccount.h"
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        string name, account;
        double num;
        cout << "enter name : ";
        getline(cin, name);
        cout << "enter bank account : ";
        getline(cin, account);
    
        BankAccount ba(name, account);
        cout << "enter the deposit amount : ";
        cin >> num;
        cin.get();
        ba.deposit(num);
        cout << "your current bank account information : ";
        ba.show();
    
        cout << "enter the withdrawal amount: ";
        cin >> num;
        cin.get();
        ba.withdraw(num);
        cout << "your current bank account information : ";
        ba.show();
    
        return 0;
    }
    
    2. 下面是一个非常简单的类定义:
    class Person
    {
    private:
        static const int LIMIT = 25;
        string lname;      // Person’s last name
        char fname[LIMIT]; // Person’s first name
    public:
        Person()
        {
            lname = "";
            fname[0] = '\0';
        }                                                    // #1
        Person(const string &ln, const char *fn = "Heyyou"); // #2
        // the following methods display lname and fname
        void Show() const;       // firstname lastname format
        void FormalShow() const; // lastname, firstname format
    };
    
    它使用了一个string对象和一个字符数组,让您能够比较它们的用法。请提供未定义的方法的代码,以完成这个类的实现。再编写一个使用这个类的程序,它使用了三种可能的构造函数的调用(没有参数、一个参数和两个参数)以及两种显示方法。下面是一个使用这些构造函数和方法的例子:
    Person one;                      // use default constructor
    Person two("Smythecraft");       // use #2 with one default argument
    Person three("Dimwiddy", "Sam"); // use #2, no defaults one.Show();
    cout << endl;
    one.FormalShow();
    // etc. for two and three
    

    Person.h :

    #ifndef PERSON_H
    #define PERSON_H
    
    #include <string>
    using std::string;
    
    class Person
    {
    private:
        static const int LIMIT = 25;
        string lname;      // Person’s last name
        char fname[LIMIT]; // Person’s first name
    public:
        Person()
        {
            lname = "";
            fname[0] = '\0';
        }                                                    // #1
        Person(const string &ln, const char *fn = "Heyyou"); // #2
        // the following methods display lname and fname
        void Show() const;       // firstname lastname format
        void FormalShow() const; // lastname, firstname format
    };
    
    #endif
    

    Person.cpp :

    #include "Person.h"
    #include <iostream>
    using std::cout;
    using std::endl;
    
    Person::Person(const string &ln, const char *fn)
    {
        lname = ln;
        strcpy(fname, fn);
    }
    
    void Person::FormalShow() const
    {
        cout << fname << " " << lname << endl;
    }
    
    void Person::Show() const
    {
        cout << fname << " , " << lname << endl;
    }
    

    main.cpp :

    #include "Person.h"
    #include <iostream>
    using std::cout;
    using std::endl;
    int main()
    {
        Person one;
        Person two("Smythecraft");
        Person three("Dimwiddy", "Sam");
        cout << "Person one : " << endl;
        one.Show();
        one.FormalShow();
        cout << "Person two : " << endl;
        two.Show();
        two.FormalShow();
        cout << "Person two : " << endl;
        three.Show();
        three.FormalShow();
        return 0;
    }
    
    3.完成第9章的编程练习1,但要用正确的golf类声明替换那里的代码。用带合适参数的构造函数替换setgolf(golf &, const char * , int),以提供初始值。保留setgolf()的交互版本,但要用构造函数来实现它(例如,setgolf()的代码应该获得数据,将数据传递给构造函数来创建一个临时对象,并将其赋给调用对象,即*this)。

    Golf.h:

    #ifndef GOLF_H
    #define GOLF_H
    
    class Golf
    {
    public:
        Golf();
        Golf(const char *name, int hc);
        int setgolf();
        void sethandicap(int hc);
        void showgolf() const;
    
    private:
        static const int Len = 40;
        char fullname[Len];
        int handicap;
    };
    
    #endif
    

    Golf.cpp:

    #include "Golf.h"
    #include <iostream>
    
    using namespace std;
    
    Golf::Golf()
    {
        strcpy(fullname, "DefaultName");
        handicap = 0;
    }
    Golf::Golf(const char *name, int hc)
    {
        strcpy(fullname, name);
        handicap = hc;
    }
    
    int Golf::setgolf()
    {
        cout << "please enter fullname : ";
        cin.getline(fullname, Len);
        if (strlen(fullname) == 0)
            return 0;
        else
        {
            cout << "please enter handicap : ";
            cin >> handicap;
            cin.get();
            return 1;
        }
    }
    
    void Golf::sethandicap(int hc)
    {
        handicap = hc;
    }
    
    void Golf::showgolf() const
    {
        cout << "fullname : " << fullname << ", handicap : " << handicap << endl;
    }
    

    main.cpp:

    #include "Golf.h"
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        Golf ann("Ann Birdfree", 24), andy, arrGolf[3];
        ann.showgolf();
    
        andy.showgolf();
        andy.setgolf();
        andy.showgolf();
        andy.sethandicap(20);
        andy.showgolf();
    
        int i = 0;
        while (i < 3 && arrGolf[i].setgolf())
        {
            arrGolf[i].showgolf();
            i++;
            if (i < 3)
                cout << "next one: " << endl;
        }
    
        return 0;
    }
    
    4.完成第9章的编程练习4,但将Sales结构及相关的函数转换为一个类及其方法。用构造函数替换setSales(sales &, double [], int)函数。用构造函数实现setSales(Slaes &)方法的交互版本。将类保留在名称空间SALES 中。

    sales.h:

    //sales.h-----头文件
    #ifndef SALES_H
    #define SALES_H
    
    namespace SALES
    {
        const int QUARTERS = 4;
        class Sales
        {
        public:
            Sales();
            Sales(const double ar[], int n);
            void showSales();
    
        private:
            double sales[QUARTERS];
            double average;
            double max;
            double min;
        };
    }
    
    #endif
    

    sales.cpp:

    //sales.cpp-----源代码文件
    #include "sales.h"
    #include <iostream>
    
    using namespace std;
    namespace SALES
    {
        Sales::Sales(const double ar[], int n)
        {
            double min = 0, max = 0, sum = 0;
            min = max = ar[0];
            for (int i = 0; i < n; i++)
            {
                sales[i] = ar[i];
                sum += ar[i];
                if (ar[i] > max)
                {
                    max = ar[i];
                }
                if (ar[i] < min)
                {
                    min = ar[i];
                }
            }
            average = sum / n;
        }
    
        Sales::Sales()
        {
            cout << "Please enter 4 quarters for sales:" << endl;
            cout << "the 1 quarter :";
            cin >> sales[0];
            min = max = sales[0];
            for (int i = 1; i < 4; i++)
            {
                cout << "the " << i << " quarter :";
                cin >> sales[i];
                if (max < sales[i])
                {
                    max = sales[i];
                }
                if (min > sales[i])
                {
                    min = sales[i];
                }
            }
            average = (sales[0] + sales[1] + sales[2] + sales[3]) / 4;
        }
    
        void Sales::showSales()
        {
            cout << "Display all information in sales : " << endl;
            cout << "The 4 quarters are $" << sales[0] << ", $" << sales[1] << ", $" << sales[2] << ", $" << sales[3] << endl;
            cout << "The average income is $" << average << endl;
            cout << "The maximum income is $" << max << endl;
            cout << "The minimum income is $" << min << endl;
        }
    }
    

    main.cpp:

    #include "sales.h"
    #include <iostream>
    
    using namespace SALES;
    int main()
    {
        double arr[4] = {3.4, 5.6, 2.5, 6.1};
        Sales s1(arr, 4);
        s1.showSales();
        Sales s2;
        s2.showSales();
        return 0;
    }
    
    5.考虑下面的结构声明:
    struct customer {
    char fullname[35];
    double payment;
    };
    
    编写一个程序,它从栈中添加和删除customer结构(栈用Stack类声明表示)。每次customer结构被删除时,其payment的值都被加入到总数中,并报告总数。注意:应该可以直接使用Stack类而不作修改;只需修改typedef声明,使Item的类型为customer,而不是unsigned long即可.

    stack.h :

    #ifndef STACK_H
    #define STACK_H
    
    struct customer
    {
        char fullname[35];
        double payment;
    };
    
    typedef customer Item;
    
    class Stack
    {
    public:
        Stack();
        bool pop(Item &it);
        bool push(const Item &it);
        bool isfull() const;
        bool isempty() const;
    
    private:
        double total;
        int top;
        enum
        {
            MAX = 10
        };
        Item item[MAX];
    };
    
    #endif
    

    stack.cpp :

    #include "stack.h"
    #include <iostream>
    
    using namespace std;
    
    Stack::Stack()
    {
        top = 0;
        total = 0;
    }
    
    bool Stack::isempty() const
    {
        return top == 0;
    }
    
    bool Stack::isfull() const
    {
        return top == MAX;
    }
    
    bool Stack::pop(Item &it)
    {
        if (top > 0)
        {
            it = item[--top];
            total += it.payment;
            cout << "An order has been processed, current total revenue : " << total << endl;
            return true;
        }
        else
        {
            return false;
        }
    }
    
    bool Stack::push(const Item &it)
    {
        if (top < MAX)
        {
            item[top++] = it;
            return true;
        }
        else
        {
            return false;
        }
    }
    

    main.cpp :

    #include "stack.h"
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        Stack stack;
        customer cu;
        char ch;
        cout << "Press a to add a customer, P to process an order, and Q to exit." << endl;
        while (cin >> ch && toupper(ch) != 'Q')
        {
            while (cin.get() != '\n')
            {
                continue;
            }
            if (!isalpha(ch))
            {
                cout << '\a';
                continue;
            }
            switch (ch)
            {
            case 'a':
            case 'A':
                if (stack.isfull())
                {
                    cout << "The order of 10 customers has been filled. Please process the existing order first !" << endl;
                }
                else
                {
                    cout << "Add customer name : ";
                    cin.getline(cu.fullname, 35);
                    cout << "Add the customer's consumption amount : ";
                    cin >> cu.payment;
                    cout << "dsssd : " << stack.push(cu);
                }
                break;
            case 'p':
            case 'P':
                if (stack.isempty())
                {
                    cout << " There are currently no unprocessed orders." << endl;
                }
                else
                {
                    stack.pop(cu);
                }
                break;
            default:
                cout << " Input error!!!" << endl;
                break;
            }
            cout << "Press a to add a customer, P to process an order, and Q to exit." << endl;
        }
        return 0;
    }
    
    6.下面是一个类声明:
    class Move
    {
    private:
        double x;
        double y;
    
    public:
        Move(double a = 0, double b = 0); //sets x, y to a, b
        showmove() const;                 // shows current x, y values
        Move add(const Move &m) const;
        // this function adds x of m to x of invoking object to get new x,
        // adds y of m to y of invoking object to get new y, creates a new
        // move object initialized to new x, y values and returns it
        reset(double a = 0, double b = 0); // resets x,y to a, b
    }
    
    请提供成员函数的定义和测试这个类的程序。

    move.h :

    #ifndef MOVE_H
    #define MOVE_H
    
    class Move
    {
    private:
        double x;
        double y;
    
    public:
        Move(double a = 0, double b = 0); //sets x, y to a, b
        void showmove() const;            // shows current x, y values
        Move add(const Move &m) const;
        // this function adds x of m to x of invoking object to get new x,
        // adds y of m to y of invoking object to get new y, creates a new
        // move object initialized to new x, y values and returns it
        void reset(double a = 0, double b = 0); // resets x,y to a, b
    };
    
    #endif
    

    move.cpp :

    #include "move.h"
    #include <iostream>
    
    Move::Move(double a, double b)
    {
        x = a;
        y = b;
    }
    
    Move Move::add(const Move &m) const
    {
        return Move(x + m.x, y + m.y);
    }
    
    void Move::showmove() const
    {
        std::cout << "x is :" << x << std::endl;
        std::cout << "y is :" << y << std::endl;
    }
    void Move::reset(double a, double b)
    {
        x = a;
        y = b;
    }
    

    main.cpp :

    #include "move.h"
    #include <iostream>
    
    int main()
    {
        Move m1(1, 2), m2(3, 4);
        m1.showmove();
        m2.showmove();
        m1.add(m2).showmove();
        m1.reset(5, 6);
        m1.showmove();
        return 0;
    }
    
    7.Betelgeusean plorg有这些特征.
    数据:
    • plorg的名称不超过19个字符;
    • plorg有满意指数(CI),这是一个整数。
    操作:
    • 新的plorg将有名称,其CI值为50;
    • plorg的CI可以修改;
    • plorg可以报告其名称和CI;
    • plorg的默认名称为“Plorga”。
    请编写一个Plorg类声明(包括数据成员和成员函数原型)来表示plorg,并编写成员函数的函数定义。然后编写一个小程序,以演示Plorg类的所有特性。

    plorg.h :

    #ifndef PLORG_H
    #define PLORG_H
    
    class Plorg
    {
    private:
        char name[19];
        int CI;
    
    public:
        Plorg();
        Plorg( const char *n, int ci);
        void show();
        void setCI(int ci);
    };
    
    #endif
    

    plorg.cpp :

    #include "plorg.h"
    #include <iostream>
    
    Plorg::Plorg()
    {
        strcpy(name, "Plorg");
        CI = 0;
    }
    Plorg::Plorg(const char *n, int ci)
    {
        strcpy(name, n);
        CI = ci;
    }
    
    void Plorg::setCI(int ci)
    {
        CI = ci;
    }
    
    void Plorg::show()
    {
        std::cout << "name : " << name << ", CI: " << CI << std::endl;
    }
    

    main.cpp :

    #include "plorg.h"
    #include <iostream>
    
    int main()
    {
        Plorg p1, p2("plorg2", 50);
        p1.show();
        p2.show();
        p1.setCI(30);
        p1.show();
    }
    
    8.可以将简单列表描述成下面这样:
    • 可存储0或多个类型的列表;

    • 可创建空列表

    • 可在列表中添加数据项;

    • 可确定列表是否为空;

    • 可确定列表是否已满;

    • 可访问列表中每一个数据项,并对它执行某种操作。

    可以看到,这个列表确实很简单,例如它不允许插入或删除数据项。
    请设计一个List类来表示这中数据类型。您应提供头文件list.h和实现文件list.cpp.前者包含定义,后者包含实现这个类的方法。您还应创建一个简短的程序来实现这个类。
    该表的规范很简单,这主要旨在简化这个编程练习,可以选择使用数组或链表来实现这个列表,但公有结构不应依赖与说做的选择。也就是说,公有接口不应有数组索引,节点指针等。应使用通用概念来表达创建列表、在列表中添加数据项等操作。对于访问数据项以及执行操作,通常应使用将函数指针做为参数的函数来处理:

    void visit(void (*pf) (Item&));

    其中,pf指向一个将Item引用作为参数的函数(不是成员函数),Item是列表中数据项的类型,visit()函数将该函数用于列表中的每个数据项。

    list.h :

    #ifndef LIST_H
    #define LIST_H
    
    typedef int Item;
    const int MAX = 10;
    class List
    {
    private:
        Item ITEM[MAX];
        int COUNT;
    
    public:
        List();
        bool isfull();
        bool isempty();
        bool addItem(Item it);
        Item *item();
        int count();
        void visit(void (*pf)(Item &));
    };
    
    #endif
    

    list.cpp :

    #include "list.h"
    #include <iostream>
    
    List::List()
    {
        COUNT = 0;
    }
    
    bool List::isfull()
    {
        return COUNT == MAX;
    }
    
    bool List::isempty()
    {
        return COUNT == 0;
    }
    bool List::addItem(Item it)
    {
        if (this->isfull())
        {
            std::cout << "full already, add fail. " << std::endl;
            return false;
        }
        else
        {
            ITEM[COUNT++] = it;
            return true;
        }
    }
    
    Item *List::item()
    {
        return ITEM;
    }
    
    int List::count()
    {
        return COUNT;
    }
    
    void List::visit(void (*pf)(Item &))
    {
        for (int i = 0; i < COUNT; i++)
        {
            (*pf)(ITEM[i]);
        }
    }
    

    main.cpp :

    #include "list.h"
    #include <iostream>
    
    void intadd2(int &n);
    
    int main()
    {
        List l;
        l.addItem(1);
        l.addItem(2);
        l.addItem(3);
        for (int i = 0; i < 3; i++)
        {
            std::cout << l.item()[i] << std::endl;
        }
        l.visit(intadd2);
        for (int i = 0; i < 3; i++)
        {
            std::cout << l.item()[i] << std::endl;
        }
        return 0;
    }
    
    void intadd2(int &n)
    {
        n += 2;
    }
    

    相关文章

      网友评论

        本文标题:C++ Primer Plus习题及答案-第十章

        本文链接:https://www.haomeiwen.com/subject/sajbartx.html