C++自修入門實境秀、C++ Primer 5版研讀秀 43/ ~v7 類別-constructors-20190907_133802
練習7.11
Sales_data.h
#pragma once
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include<string>
using namespace std;//千萬不要忘了這個
struct Sales_data {
Sales_data() = default;//預設建構器(constructor)用這式會較Sales_data() {}多二個建構器,蓋=default由編譯器創建2個額外的合成的預設建構器(synthesized default constructors) 56:00
//Sales_data() :bookNo{"000-000-000" } {}
Sales_data(const string &bNo) :bookNo{bNo } {}
Sales_data(const string &bNo, const double bSize, const double rvn) :bookNo{ bNo }, bookSize{ bSize }, revenue{rvn} {}
Sales_data(const string &, const double bSize, const double, const unsigned);//在類別外定義的建構器
Sales_data(istream &);//在類別外定義的建構器
//Sales_data() {}//與Sales_data() = default;應是一樣的,然不能寫在最前面,會遮蔽後面的建構器 50:00
string bookNo;
double revenue{ 0.00 };//總營收-營業額
unsigned soldQ{ 0 };
double bookSize{0.00};
Sales_data& combine(const Sales_data&, const Sales_data&);//成員函式宣告一定要在類別內,定義可在此外
Sales_data& combine(const Sales_data&);//要改變this及其屬性值就不能再在參數列後加上const;因為加上const後this成了指向常值的常值指標,被指向的東西是不能被改變的了
string isbn()const;
double avg_price()const;
};
ostream& print(ostream& , const Sales_data&);
istream& read(istream& , Sales_data& );
Sales_data add(const Sales_data&, const Sales_data&);
#endif // !SALES_DATA_H
Sales_data.cpp:
#include "Sales_data.h"
#include<string>
#include<iostream>
using namespace std;
Sales_data::Sales_data(const string& bNo,const double bSize,const double price, const unsigned sdQ) {
bookNo = bNo; soldQ = sdQ; revenue = price * sdQ; bookSize = bSize;
}
Sales_data::Sales_data(istream& is)
{
read(is, *this);
}
Sales_data& Sales_data::combine(const Sales_data& sales_data1, const Sales_data& sales_data2)
{
this->bookNo = sales_data1.bookNo;
this->bookSize = sales_data1.bookSize;
this->soldQ = sales_data1.soldQ + sales_data2.soldQ;
this->revenue = sales_data1.revenue + sales_data2.revenue;
return *this; // TODO: insert return statement here
}
Sales_data& Sales_data::combine(const Sales_data& sales_data)
{
if (bookNo == "") bookNo = sales_data.bookNo;//因為這是Sales_data類別的成員函式,所以可以直接調用該類別內的所有成員名稱,不必全名稱
bookSize = sales_data.bookSize;
soldQ += sales_data.soldQ;
revenue += sales_data.revenue;
return *this;// TODO: insert return statement here
}
string Sales_data::isbn()const
{
return bookNo;
}
double Sales_data::avg_price()const
{
if (soldQ>0)
{
return revenue / soldQ;
}
return 0.0;
}
ostream& print(ostream& os, const Sales_data& sales_data) {
os << sales_data.isbn() << '\t' << sales_data.soldQ << '\t'
<< sales_data.revenue << '\t' << sales_data.avg_price();
return os;
}
istream& read(istream& is, Sales_data& sales_data) {//要改變引數值,參數一定要是參考,將引數用傳址(參考)方式傳遞
//decltype(cin)& read(istream is ,Sales_data sales_data) {
is >> sales_data.bookNo >> sales_data.soldQ >> sales_data.revenue;
return is;
}
Sales_data add(const Sales_data& sales_data1, const Sales_data& sales_data2)
{
Sales_data sum = sales_data1;
sum.combine(sales_data2);
return sum;
}
Run:
#include<vector>
#include "Sales_data.h"
#include <iostream>
using namespace std;
int main() {
Sales_data sd ;//和下式一樣,只是在Visual Studio預選清單中,它是從第2個建構器來讓我們選的
Sales_data sd1 = Sales_data();//可見Sales_data sd的Sales_data() 就是預設的第一個建構器
Sales_data& rSd=sd; Sales_data& rrSd=rSd;
Sales_data sd2= Sales_data(rSd);//這2個建構器是編譯器自己訂的
Sales_data sd21= Sales_data(rrSd);//這2個建構器是編譯器自己訂的
Sales_data sd3= Sales_data(cin);//這個在建構時須輸入才能執行
Sales_data sd4= Sales_data("978-986-502-172-6(平裝)");
Sales_data sd5= Sales_data("978-986-502-172-6(平裝)",24.01,310.11);
Sales_data sd6= Sales_data("978-986-502-172-6(平裝)",24.01, 110.1,3);
const vector<Sales_data> vecSd{sd,rSd,rrSd,sd1,sd2,sd21,sd3,sd4,sd5,sd6};
for (Sales_data i:vecSd)
{
print(cout,i)<<"\n"<<endl;
}
}
2:7:30
練習7.12
2:11:30
#pragma once
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include<string>
using namespace std;//千萬不要忘了這個
struct Sales_data {
Sales_data() = default;//預設建構器(constructor)用這式會較Sales_data() {}多二個建構器,蓋=default由編譯器創建2個額外的合成的預設建構器(synthesized default constructors) 56:00
//Sales_data() :bookNo{"000-000-000" } {}
Sales_data(const string &bNo) :bookNo{bNo } {}
Sales_data(const string &bNo, const double bSize, const double rvn) :bookNo{ bNo }, bookSize{ bSize }, revenue{rvn} {}
Sales_data(const string &, const double bSize, const double, const unsigned);//在類別外定義的建構器
//Sales_data(istream &);//在類別外定義的建構器
2:19:59
練習7.13
3:24:00
#include "Sales_data.h"
#include <iostream>
using namespace std;
int main() {
Sales_data total=Sales_data(cin);//存放累計和的變數
//if (read(cin, total)) {//選取第一筆交易記錄
if (total.readSeccess) {//選取第一筆交易記錄
Sales_data trans=Sales_data(cin);//存放資料給下一筆交易記錄使用的變數
//while(read(cin, trans)) { //選取剩餘的交易記錄
while(trans.readSeccess) { //選取剩餘的交易記錄
if (total. isbn ()==trans.isbn())//檢查isbns
total.combine(trans);//更新累計總和
else {
print(cout, total) << endl;//印出結果
total=trans ;//處理下一本書
}
if(!read(cin, trans))trans.readSeccess=false;//還要再選取下一筆交易記錄,讓trans移位
}
print(cout,total) << endl;//印出最後一筆交易記錄
}
else {
cerr << "No data?!" << endl;//通知使用者
}
}
另一式:while要改成 do while才行,因為第2筆已讀取
#include "Sales_data.h"
#include <iostream>
using namespace std;
int main() {
Sales_data total=Sales_data(cin);//存放累計和的變數
//if (read(cin, total)) {//選取第一筆交易記錄
if (total.readSeccess) {//選取第一筆交易記錄
Sales_data trans=Sales_data(cin);//存放資料給下一筆交易記錄使用的變數
//while(read(cin, trans)) { //選取剩餘的交易記錄
do { //選取剩餘的交易記錄
if (total. isbn ()==trans.isbn())//檢查isbns
total.combine(trans);//更新累計總和
else {
print(cout, total) << endl;//印出結果
total=trans ;//處理下一本書
}
} while (read(cin, trans));
print(cout,total) << endl;//印出最後一筆交易記錄
}
else {
cerr << "No data?!" << endl;//通知使用者
}
}
Sales_data.cpp:
#include "Sales_data.h"
#include<string>
#include<iostream>
using namespace std;
Sales_data::Sales_data(istream& is) {
if (read(is, *this)) readSeccess = true;
}
Sales_data::Sales_data(const string& bNo,const double bSize,const double price, const unsigned sdQ) {
bookNo = bNo; soldQ = sdQ; revenue = price * sdQ; bookSize = bSize;
}
Sales_data& Sales_data::combine(const Sales_data& sales_data1, const Sales_data& sales_data2)
{
this->bookNo = sales_data1.bookNo;
this->bookSize = sales_data1.bookSize;
this->soldQ = sales_data1.soldQ + sales_data2.soldQ;
this->revenue = sales_data1.revenue + sales_data2.revenue;
return *this; // TODO: insert return statement here
}
Sales_data& Sales_data::combine(const Sales_data& sales_data)
{
if (bookNo == "") bookNo = sales_data.bookNo;//因為這是Sales_data類別的成員函式,所以可以直接調用該類別內的所有成員名稱,不必全名稱
bookSize = sales_data.bookSize;
soldQ += sales_data.soldQ;
revenue += sales_data.revenue;
return *this;// TODO: insert return statement here
}
string Sales_data::isbn()const
{
return bookNo;
}
double Sales_data::avg_price()const
{
if (soldQ>0)
{
return revenue / soldQ;
}
return 0.0;
}
ostream& print(ostream& os, const Sales_data& sales_data) {
os << sales_data.isbn() << '\t' << sales_data.soldQ << '\t'
<< sales_data.revenue << '\t' << sales_data.avg_price();
return os;
}
istream& read(istream& is, Sales_data& sales_data) {//要改變引數值,參數一定要是參考,將引數用傳址(參考)方式傳遞
//decltype(cin)& read(istream is ,Sales_data sales_data) {
is >> sales_data.bookNo >> sales_data.soldQ >> sales_data.revenue;
return is;
}
Sales_data add(const Sales_data& sales_data1, const Sales_data& sales_data2)
{
Sales_data sum = sales_data1;
sum.combine(sales_data2);
return sum;
}
Sales_data.h:
#pragma once
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include<string>
using namespace std;//千萬不要忘了這個
struct Sales_data {
Sales_data() = default;//預設建構器(constructor)用這式會較Sales_data() {}多二個建構器,蓋=default由編譯器創建2個額外的合成的預設建構器(synthesized default constructors) 56:00
//Sales_data() {}//與Sales_data() = default;應是一樣的,然不能寫在最前面,會遮蔽後面的建構器 50:00
//Sales_data() :bookNo{"000-000-000" } {}
Sales_data(const string &bNo) :bookNo{bNo } {}
Sales_data(const string &bNo, const double bSize, const double rvn) :bookNo{ bNo }, bookSize{ bSize }, revenue{rvn} {}
Sales_data(const string &, const double bSize, const double, const unsigned);//在類別外定義的建構器
Sales_data(istream &);//在類別外定義的建構器
//Sales_data(istream& is){read(is, *this);}
bool readSeccess=false;//readSeccess記錄選取成功否
string bookNo;
double revenue{ 0.00 };//總營收-營業額
unsigned soldQ{ 0 };
double bookSize{0.00};
Sales_data& combine(const Sales_data&, const Sales_data&);//成員函式宣告一定要在類別內,定義可在此外
Sales_data& combine(const Sales_data&);//要改變this及其屬性值就不能再在參數列後加上const;因為加上const後this成了指向常值的常值指標,被指向的東西是不能被改變的了
string isbn()const;
double avg_price()const;
};
ostream& print(ostream& , const Sales_data&);
istream& read(istream& , Sales_data& );
Sales_data add(const Sales_data&, const Sales_data&);
#endif // !SALES_DATA_H
練習7.14
3:38:50
#include "Sales_data.h"
#include <iostream>
using namespace std;
int main() {
Sales_data sd;
print(cout, sd)<<endl;
}
Sales_data.h:
struct Sales_data {
Sales_data() {
readSeccess = false ; bookNo = "";
revenue = 0.00; soldQ = 0; bookSize = 0.00;
}
//Sales_data() = default;//預設建構器(constructor)用這式會較Sales_data() {}多二個建構器,蓋=default由編譯器創建2個額外的合成的預設建構器(synthesized default constructors)
3:50:30
練習7.15
Person.h
#ifndef PERSON_H
#define PERSON_H
#include<string>
#include<iostream>
using namespace std;
struct Person{
//Person()=default;
Person(){
name = "someone";
address = "somewhere";
}
Person(const string name, const string& address) :name(name),address(address){}
Person(istream&);
string name;
string address ;
string addressMethod()const;
string nameMethod()const;
};
istream& read(istream&,Person&);
ostream& print(ostream&,const Person&);
#endif
Person.cpp
#include "Person.h"
Person::Person(istream& is)
{
read(cin, *this);
}
string Person::addressMethod() const
{
return address;
}
string Person::nameMethod() const
{
return name;
}
istream& read(istream& is,Person& p){
is>>p.name>>p.address;
return is;
}
ostream& print(ostream& os,const Person& p){
os<<p.nameMethod()<<'\t'<<p.addressMethod();
return os;
}
Run:
#include<vector>
#include "Person.h"
#include <iostream>
using namespace std;
int main() {
Person p;
Person p1 = Person("孫守真", "士林區");
Person p2 = Person(cin);
vector<Person>vecPerson{ p,p1,p2 };
for(Person p:vecPerson)
print(cout,p)<<endl;
}
3:52:50 未錄到的請看臉書直播 第165集
7.1.5. Copy, Assignment, and Destruction
留言