C++ Primer Plus 第十章答案 对象和类

简介: 只有聪明人才能看见的摘要~( ̄▽ ̄~)~

复习题

//10.9
//1
类是用户定义的类型的定义。类声明指定了数据将如何储存
同时指定了用来访问和操作这些数据的方法(类成员函数)
//2
类表示人们可以通过类方法的公有接口对类对象执行的操作,这是抽象
类的数据成员可以是私有的(private为默认),这意味着只能通过成员函数来访问这些数据,这是数据隐藏
实现的具体细节(如数据的显示和方法的代码)都是隐藏的,这是封装
//3
类定义了一种类型,包括如何使用它。对象是一个变量或其他数据对象(如由new产生的)
并根据类定义被创建和使用。类和对象的关系和标准类型和它的变量的关系相同
//4
如果创建给定类的多个对象,则每个对象都有其自己的数据内存空间,但是所有对象都
使用同一组成员函数(通常,方法是公有的而数据是私有的,但这只是策略方面的问题,并不是对类的要求)
//5
class Bank_account {
private:
  string b_name;
  string b_accountnum;
  double b_deposit;
public:
  Bank_account();
  Bank_account(const string& name, const string& accountnum, double deposit = 0.0);
  ~Bank_account();
  void show()const;
  void deposit(double deposit);
  void take(double take);
};
//6
创建类对象或显式调用构造函数时,类的构造函数被调用
对象过期时,调用类的析构函数
//7
Bank_account::Bank_account(const string& name, const string& account, double deposit = 0.0) {
  b_name = name;
  b_account = account;
  if (deposit < 0) {
    cout << "Error!Set to 0.\n";
    b_deposit = 0;
  }
  else
    b_deposit = deposit;
}
//8
默认构造函数是没有参数或者所有参数都有默认值的构造函数。拥有默认构造函数后
可以声明对象而不初始化它,即使已经定义了初始化构造函数。它还使得能声明数组
//9
class Stock {
private:
  std::string company;
  int shares;
  double share_val;
  double total_val;
  void set_tot() { total_val = shares * shara_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 Stock& topval(const Stock& s)const;
  int shares()const { return shares; }
  double share_val()const { return share_val; }
  double total_val()const { return total_val; }
  const std::string& company()const { return company; }
};
//10
this指针是类方法可以使用的指针,它指向用于调用方法的对象
因此,this是对象的地址,*this是对象本身

image.gif

编程练习

practice 1

#pragma once//避免此头文件被包含多次,和#ifndef的作用类似
//Bank.h
#ifndef BANK_H_
#define BANK_H_
#include<string>
using namespace std;
class Bank_account {
private:
  string b_name;
  string b_accountnum;
  double b_deposit;
public:
  Bank_account();
  Bank_account(const string& name, const string& accountnum, double deposit);
  ~Bank_account();
  void show()const;
  void deposit(double deposit);
  void take(double take);
};
#endif
//Bank.cpp
#include"Bank.h"
#include<iostream>
#include<string>
using namespace std;
Bank_account::Bank_account() {
  b_name = "no name";
  b_accountnum = "\0";
  b_deposit = 0.0;
}
Bank_account::Bank_account(const string& name, const string& accountnum, double deposit) {
  b_name = name;
  b_accountnum = accountnum;
  if (deposit < 0) {
    cout << "Error!Set to 0.\n";
    b_deposit = 0;
  }
  else
    b_deposit = deposit;
}
Bank_account::~Bank_account() {}
void Bank_account::show()const {
  cout << "The information of " << b_name << "'s bank account: \n";
  cout << "name: " << b_name << " accountnum: " << b_accountnum << endl;
  cout << "deposit: " << b_deposit << endl;
}
void Bank_account::deposit(double deposit) {
  if (deposit < 0)
    cout << "Number of deposit can't be nagative.\n";
  else
    b_deposit += deposit;
}
void Bank_account::take(double take) {
  if (take < 0)
    cout << "Number of take from account can't be nagative.\n";
  else if (take > b_deposit)
    cout << "You can't take from account more than it has.\n";
  else
    b_deposit -= take;
}
//main.cpp
#include"Bank.h"
int main() {
  using namespace std;
  Bank_account yue;
  yue.show();
  yue = { "yue","1234567",-100.0 };
  yue.show();
  yue = { "yue","1234567",100.0 };
  yue.show();
  yue.deposit(-12.1);
  yue.show();
  yue.deposit(12.1);
  yue.show();
  yue.take(-25.5);
  yue.show();
  yue.take(112.1);
  yue.show();
  yue.take(25.5);
  yue.show();
  return 0;
}

image.gif

practice 2

#pragma once
//person.h
#ifndef PERSON_H_
#define PERSON_H_
#include<string>
#include<cstring>
using namespace std;
class Person {
private:
  static const int LIMIT = 25;
  string lname;
  char fname[LIMIT];
public:
  Person() { lname = "", fname[0] = '\0'; }
  Person(const string& ln, const char* fn = "Heyyou");
  void show()const;
  void formalshow()const;
};
#endif
//person.cpp
#include"person.h"
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
Person::Person(const string& ln, const char* fn) {
  lname = ln;
  strcpy_s(fname, fn);
}
void Person::show()const {
  cout << "Show the name for person: " << this->fname << endl;//或者使用(*this).fname
  cout << "The firstname: " << fname << endl;
  cout << "The lastname: " << lname << endl;
}
void Person::formalshow()const {
  cout << "Show the name for person: " << this->fname << endl;
  cout << "The lastname: " << lname << endl;
  cout << "The firstname: " << fname << endl;
}
//main.cpp
#include"person.h"
#include<iostream>
int main() {
  using std::endl;
  Person one;
  Person two("Smythecraft");
  Person three("Dimwiddy", "Sam");
  one.show();
  one.formalshow();
  cout << endl;
  two.show();
  two.formalshow();
  cout << endl;
  three.show();
  three.formalshow();
  cout << endl;
  return 0;
}

image.gif

practice 3

#pragma once
//golf.h
#ifndef GOLF_H_
#define GOLF_H_
const int Len = 40;
class Golf {
private:
  char fullname[Len];
  int g_handicap;
public:
  Golf(const char* name, int hc);
  Golf();
  void setgolf();
  const char* rtfname();//要实现输入名字为空时结束循环,因此要一个成员函数返回私有数据比较
  void handicap(int hc);//此处函数名和私有数据同名
  //后面的赋值会报错,所以给私有数据名加了前缀g_handicap
  void showgolf()const;
};
#endif
//golf.cpp
#include"golf.h"
#include<iostream>
#include<cstring>
using namespace std;
Golf::Golf(const char* name, int hc) {
  strcpy_s(fullname, name);
  g_handicap = hc;
}
Golf::Golf() {
  strcpy_s(fullname, "no name");
  g_handicap = 0;
}
void Golf::setgolf() {
  cout << "Please enter the information for golf" << endl;
  Golf golf;
  cout << "The fullname: ";
  cin.getline(golf.fullname, Len);
  cout << "The handicap: ";
  cin >> golf.g_handicap;
  cin.get();//凡是输入使用getline()使都要考虑之前的输入是否有
  //换行符留在输入队列中,使用cin.get()丢弃换行符
  *this = golf;
}
const char* Golf::rtfname() {
  return fullname;
}
void Golf::handicap(int hc) {
  g_handicap = hc;
}
void Golf::showgolf()const {
  cout << "The information of " << fullname << ": \n";
  cout << "Fullname: " << fullname << endl;
  cout << "Handicap: " << g_handicap << endl;
}
//main.cpp
#include"golf.h"
#include<iostream>
int main() {
  Golf g1;
  g1.showgolf();
  Golf g[3];
  for (int i = 0; i < 3; i++) {
    g[i].setgolf();
    if (g[i].rtfname()[0]== '\0')//这里在调用setgolf输入名字时使用了cin.getline()
      //它会把换行符变为空字符储存在字符串里,因此检查第一个字符
      // 我不会太具体的解释具体为什么==""不对
      break;
      g[i].showgolf();
  }
  g1.handicap(100);
  g1.showgolf();
  return 0;
}

image.gif

practice 4

//sale.h
#ifndef SALE_H_
#define SALE_H_
namespace SALES {
  const int QUARTERS = 4;
  class Sales {
  private:
    double sales[QUARTERS];
    double average;
    double min;
    double max;
  public:
    Sales(const double ar[], int n=4);
    Sales();
    void setsales();
    void showsales();
  };
}
#endif
//sale.cpp
#include"sale.h"
#include<iostream>
namespace SALES {
  using namespace std;
  Sales::Sales(const double ar[], int n) {
    double mx = ar[0];
    double mn = ar[0];
    double total = 0;
    for (int i = 0; i < n; i++) {
      sales[i] = ar[i];
      total += ar[i];
      if (mx < ar[i])
        mx = ar[i];
      if (mn > ar[i])
        mn = ar[i];
    }
    average = total / n;
    max = mx; min = mn;
  }
  Sales::Sales() {
    sales[0] = sales[1] = sales[2] = sales[3] = 0;
    min = max = average = 0;
  }
  void Sales::setsales() {
    cout << "Enter an array treat as sales of quarters:(most at 4)";
    double arr[4] = {};
    int i = 0;
    for (i; i < 4; i++) {
      if (cin >> arr[i]);
      else
        break;
    }
    *this = Sales(arr, i);
  }
  void Sales::showsales() {
    cout << "Here is the information of sales of quarters: \n";
    cout << "Every sale: " << sales[0] << "    " << sales[1] << "    " << sales[2]
      << "    " << sales[3] << endl;
    cout << "Average: " << average << endl;
    cout << "The max sale: " << max << endl;
    cout << "The min sale: " << min << endl;
    cout << endl;
  }
}
//main.cpp
#include"sale.h"
int main() {
  using namespace SALES;
  double ar[4] = { 90,80,120,110 };
  Sales s1(ar, 4);
  s1.showsales();
  Sales s2;
  s2.setsales();
  s2.showsales();
  return 0;
}

image.gif

practice 5

//stack.h
#ifndef STACK_H_
#define STACK_H_
struct customer {
  char fullname[35];
  double payment;
};
typedef customer Item;
class Stack {
private:
  enum{MAX=10};
  Item items[MAX];
  int top;
public:
  Stack();
  bool isempty()const;
  bool isfull()const;
  bool push(const Item& item);
  bool pop(Item& item);
};
#endif
//stack.cpp
#include"stack.h"
#include<iostream>
Stack::Stack() { top = 0; }
bool Stack::isempty()const {
  return top == 0;
}
bool Stack::isfull()const {
  return top == MAX;
}
bool Stack::push(const Item& item) {
  if (top < MAX) {
    items[top++] = item;
    return true;
  }
  else
    return false;
}
bool Stack::pop(Item& item) {
  static double total = 0;
  if (top > 0) {
    item = items[--top];
    total += item.payment;
    std::cout << "The total payment is: " << total << std::endl;
    return true;
  }
  else return false;
}
//main.cpp
#include"stack.h"
#include<iostream>
int main() {
  Stack stack;
  customer c[5]{
    {"yue",120},
    {"yue yeui",500},
    {"yue aishai",200.5},
    {"yue yue",101},
    {"yue ",82.3}
  };
  for (int i = 0; i < 5; i++)
    stack.push(c[i]);
  for (int i = 4; i >= 0; i--)
    stack.pop(c[i]);
  return 0;
}

image.gif

practice 6

//move.h
class Move {
private:
  double x;
  double y;
public:
  Move(double a = 0, double b = 0);
  void showmove()const;
  Move add(const Move& m)const;
  void reset(double a = 0, double b = 0);
};
//move.cpp
#include<iostream>
#include"move.h"
Move::Move(double a,double b) {
  x = a;
  y = b;
}
void Move::showmove()const {
  std::cout << "x = " << x << ", y = " << y << std::endl;
}
Move Move::add(const Move& m)const {
  Move mm;
  mm.x = x + m.x;
  mm.y = y + m.y;
  return mm;
}
void Move::reset(double a, double b) {
  x = a;
  y = b;
}
//main.cpp
#include"move.h"
int main() {
  Move m1(1.1, 2.2);
  m1.showmove();
  Move m2(2.2, 3.3);
  m2.showmove();
  Move m3;
  m3 = m2.add(m1);
  m3.showmove();
  m3.reset(10, 11);
  m3.showmove();
  return 0;
}

image.gif

practice 7

//plorg.h
#ifndef PLORG_H_
#define PLORG_H_
class Plorg {
private:
  char name[20];
  int CI;
public:
  Plorg(const char* n = "Plorga", int ci = 50);
  void resetci(int ci);
  char* rtname();
  int rtci();
};
#endif
//plorg.cpp
#include"plorg.h"
#include<cstring>
Plorg::Plorg(const char* n, int ci) {
  strcpy_s(name, n);
  CI = ci;
}
void Plorg::resetci(int ci) {
  CI = ci;
}
char* Plorg::rtname() {
  return name;
}
int Plorg::rtci() {
  return CI;
}
//main.cpp
#include"plorg.h"
#include<iostream>
using std::cout;
using std::endl;
int main() {
  Plorg p1("Binlang");
  cout << "p1: name: " << p1.rtname() << ", CI: " << p1.rtci() << endl;
  Plorg p2("yue", 100);
  cout << "p2: name: " << p2.rtname() << ", CI: " << p2.rtci() << endl;
  p2.resetci(150);
  cout << "p2: name: " << p2.rtname() << ", CI: " << p2.rtci() << endl;
  Plorg p3;
  cout << "p3: name: " << p3.rtname() << ", CI: " << p3.rtci() << endl;
  return 0;
}

image.gif

practice 8

//list.h
#ifndef LIST_H_
#define LIST_H_
const int MAX = 5;
struct people {
  char name[30];
  int age;
};
typedef people Item;
class List {
private:
  Item items[MAX];
  int head;
  int tail;
public:
  List();
  bool add(Item& item);
  bool get(Item& item);
  void visit(void(*pf)(Item&));
  void show()const;
};
void agedouble(Item&);
#endif
//list.cpp
#include"list.h"
#include<iostream>
using namespace std;
List::List() {
  for(int i=0;i<5;i++)
    items[i] = { "NONE",0 };
  head = 0;
  tail = 0;
}
bool List::add(Item& item) {
  if ((tail + 1) % MAX == head) {
    cout << "The list is fall!\n";
    return false;
  }
  else {
    items[tail] = item;
    tail = (tail + 1) % MAX;
  }
  return true;
}
bool List::get(Item& item) {
  if (tail == head) {
    cout << "The list is empty!\n";
    return false;
  }
  else {
    item = items[head];
    items[head] = { "NONE",0 };
    head = (head + 1) % MAX;
  }
  return true;
}
void List::visit(void(*pf)(Item&)) {
  for (int i = 0; i < MAX; i++)
    (*pf)(items[i]);
}
void List::show()const {
  for (int i = 0; i < MAX; i++)
    cout << "items[" << i << "]= " << items[i].name
    << ", " << items[i].age << endl;
  cout << endl;
}
void agedouble(Item& item) {
  item.age *= 2;
}
//main.cpp
#include"List.h"
#include<iostream>
int main() {
  using std::cout;
  using std::endl;
  List list;
  people p[5]{
    {"yue",12},
    {"yuei",13},
    {"yues",10},
    {"yuea",20},
    {"yuejs",18}
  };
  for (int i = 0; i < 5; i++) {// 队列只能读取四个元素,需要一个空间作为队满的判断
      list.add(p[i]);
    cout << p[i].name << "    " << p[i].age << endl;
  }
  list.show();
  void (*pdouble)(Item&) = agedouble;
  list.visit(pdouble);
  list.show();
  for (int i = 4; i >= 0; i--) {
    list.get(p[i]);
    cout << p[i].name << "    " << p[i].age << endl;
  }cout << endl;
  list.show();
  return 0;
}

image.gif

image.gif编辑

创建一个people[5]的数组。然后for循环,每次循环add一个people结构到List类,每次循环显示people结构的内容。add失败会显示列表已满。show()。然后调用一个以函数指针为参数(指向一个翻倍people结构的age成员的函数)的成员函数,show()。再for循环,每次循环get一个people结构,每次循环显示get的people的信息。get失败会显示列表已空。show()

相关文章
|
3月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
78 0
|
3月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
158 0
|
5月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
158 12
|
6月前
|
编译器 C++
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
|
6月前
|
存储 编译器 C++
类和对象(上)(C++)
本篇内容主要讲解了C++中类的相关知识,包括类的定义、实例化及this指针的作用。详细说明了类的定义格式、成员函数默认为inline、访问限定符(public、protected、private)的使用规则,以及class与struct的区别。同时分析了类实例化的概念,对象大小的计算规则和内存对齐原则。最后介绍了this指针的工作机制,解释了成员函数如何通过隐含的this指针区分不同对象的数据。这些知识点帮助我们更好地理解C++中类的封装性和对象的实现原理。
|
6月前
|
编译器 C++
类和对象(下)C++
本内容主要讲解C++中的初始化列表、类型转换、静态成员、友元、内部类、匿名对象及对象拷贝时的编译器优化。初始化列表用于成员变量定义初始化,尤其对引用、const及无默认构造函数的类类型变量至关重要。类型转换中,`explicit`可禁用隐式转换。静态成员属类而非对象,受访问限定符约束。内部类是独立类,可增强封装性。匿名对象生命周期短,常用于临时场景。编译器会优化对象拷贝以提高效率。最后,鼓励大家通过重复练习提升技能!
|
7月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
6月前
|
设计模式 安全 C++
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
123 16
|
7月前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
6月前
|
安全 C++
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
317 6