C++primer 第十四章 C++的代码重用

it2026-08-28  5

1.包含对象成员的类student类

main.cpp

#include <iostream> #include "studentc.hpp" using namespace std; void set(Student & sa, int n) { cout << "Please enter the student's name: "; getline(cin, sa); cout << "Please enter " << n << " quize score :\n"; for (int i = 0 ; i < n; ++i) cin >> sa[i]; while (cin.get() != '\n') continue; } const int pupils = 3; const int quizzes = 5; int main() { Student ada[pupils] = { Student(quizzes), Student(quizzes), Student(quizzes) }; int i; for (i = 0; i<pupils; ++i) set(ada[i], quizzes); cout << "\nStudent List:\n"; for (int i = 0; i < pupils; ++i) cout << ada[i].Name() << endl; cout << "\nResults:"; for (i = 0; i < pupils; ++i) { cout << endl << ada[i]; cout << "average: " << ada[i].Average() << endl; } cout << "Done.\n"; return 0; }

.hpp

#ifndef studentc_hpp #define studentc_hpp #include <iostream> #include <stdio.h> #include <string> #include <valarray> class Student { private: typedef std::valarray<double> ArrayDb; // 只能在Student类中使用 这样的写法:valarray<double> == ArrayDb std::string name; ArrayDb scores; // private method for scores output std::ostream & arr_out(std::ostream & os) const; public: Student() : name("Null Student"), scores(){} explicit Student(const std::string & s) : name(s),scores(){} explicit Student(int n) : name("Nully"), scores(n){} // doh = 5; 转换函数 还记得吗? // 就是可以用一个参数调用的构造函数将用作从参数类型转换到类类型的隐式函数 // 这个就是,是不是有点愚蠢,doh = 5;这句话它会帮你生成一个Student(5)的对象 // 你得关掉这种属性 就要用关键字 explicit Student(const std::string & s, int n) : name(s), scores(n){} // 初始化顺序按被声明的顺序 而不是: name(s), scores(n)的顺序 Student(const std::string & s, const ArrayDb &a) : name(s), scores(a){} Student(const char * str, const double *pd,int n) : name(str), scores(pd, n){} ~Student(){} double Average() const; const std::string & Name() const; double & operator[](int i); double operator[](int i) const; friend std::istream & operator>>(std::istream & is,Student &s); friend std::istream & getline(std::istream & is,Student &s); friend std::ostream & operator<<(std::ostream & os,Student &s); }; #endif /* studentc_hpp */

.cpp

#include "studentc.hpp" using namespace std; ostream & Student::arr_out(ostream & os) const { int i; int lim = (int)scores.size(); if (lim > 0) { for (i = 0; i < lim; ++i) { os << scores[i] << " "; if(i % 5 ==4) os << endl; } if (i % 5 != 0) { os << endl; } } else os << " empty array" ; return os; } double Student::Average() const { if (scores.size()>0) return scores.sum()/scores.size(); else return 0; } const std::string & Student::Name() const { return name; } double & Student::operator[](int i) { return scores[i]; } double Student::operator[](int i) const { return scores[i]; } std::istream & operator>>(std::istream & is,Student &s) { is >> s.name; return is; } std::istream & getline(std::istream & is,Student &s) { getline(is, s.name); return is; } std::ostream & operator<<(std::ostream & os,Student &s) { os << "Scores for " << s.name << ":\n"; s.arr_out(os); return os; }

2.私有继承的student类

.hpp

#ifndef studenti_hpp #define studenti_hpp #include <stdio.h> #include <iostream> #include <valarray> #include <string> using namespace std; class Student : private string ,private valarray<double> { private: typedef valarray<double> ArrayDb; ostream & arr_out(ostream & os) const; public: Student() : string("Null Student"), ArrayDb(){} explicit Student(const string & s) : string(s), ArrayDb(){} explicit Student(int n) : string("Nully"), ArrayDb(n){} Student(const string & s, int n) : string(s),ArrayDb(n){} Student(const string & s, const ArrayDb & a) : string(s),ArrayDb(a){} Student(const char * str, const double * pd, int n) : string(str),ArrayDb(pd,n){} ~Student(){} double Average() const; double & operator[](int i); double operator[](int i) const; const string & Name() const; friend std::istream & operator>>(std::istream & is,Student &s); friend std::istream & getline(std::istream & is,Student &s); friend std::ostream & operator<<(std::ostream & os,Student &s); }; #endif /* studenti_hpp */

.cpp

#include "studenti.hpp" using namespace std; double Student::Average() const { if (ArrayDb::size() > 0) return ArrayDb::sum()/ArrayDb::size(); else return 0; } double & Student::operator[](int i) { return ArrayDb::operator[](i); } double Student::operator[](int i) const { return ArrayDb::operator[](i); } const string & Student::Name() const { return (const string &) *this; } ostream & Student::arr_out(ostream & os) const { int i; int lim = (int)ArrayDb::size(); if (lim > 0) { for (i = 0; i < lim; ++i) { os << ArrayDb::operator[](i) << " "; if(i % 5 ==4) os << endl; } if (i % 5 != 0) { os << endl; } } else os << " empty array" ; return os; } istream & operator>>(istream & is,Student &s) { is >> (string &)s; return is; } istream & getline(istream & is,Student &s) { getline(is, (string &)s); return is; } ostream & operator<<(ostream & os,Student &s) { os << "Scores for " << (const string &)s << ":\n"; s.arr_out(os); return os; }

3.MI多重继承

main

#include <iostream> #include "work01.hpp" #include <cstring> const int SIZE = 5; using std::cin; using std::cout; using std::endl; using std::strchr; int main() { Worker * lalas[SIZE]; int ct; for (ct = 0; ct < SIZE; ++ct) { char choice; cout << "Enter the employee category: \n" << "w: waiter s: singer\n" << "t : singing waiter q: quit\n"; cin >> choice; while (strchr("wstq", choice) == nullptr) { cout << "Please enter a w, s, t, q: "; cin >> choice; } if (choice == 'q') { break; } switch (choice) { case 'w': lalas[ct] = new Waiter; break; case 's': lalas[ct] = new Singer; break; case 't': lalas[ct] = new SingingWaiter; break; } cin.get(); lalas[ct]->Set(); } cout << "\nHere is your staff:\n"; for (int i = 0; i < ct; ++i) { cout << endl; lalas[i]->Show(); } for (int i = 0; i < ct; ++i) { delete lalas[i]; } cout << "Done"; return 0; }

.hpp

#ifndef work01_hpp #define work01_hpp #include <string> #include <stdio.h> class Worker { private: std::string fullname; long id; protected: virtual void Data() const; virtual void Get(); public: Worker() : fullname("no one"), id(0L){} Worker(const std::string & s, long n) : fullname(s), id(n){} virtual ~Worker() = 0; // 纯虚构函数 virtual void Set() = 0; virtual void Show() const = 0; }; class Waiter : virtual public Worker { private: int panache; protected: void Data() const; void Get(); public: Waiter() : Worker(),panache(0){} Waiter(const std::string & s, long n, int p = 0) : Worker(s, n),panache(p){} Waiter(const Worker &wk, int p = 0) : Worker(wk),panache(p){} void Set(); void Show() const; }; class Singer : virtual public Worker { protected: enum{other, alto, contralto, soprano, bass, baritone, tenor}; enum{Vtypes = 7}; virtual void Data() const; virtual void Get(); private: static char *pv[Vtypes]; int voice; public: Singer() : Worker(), voice(other){} Singer(const std::string & s, long n, int v = other) : Worker(s, n), voice(v){} Singer(const Worker &wk, int v = other) : Worker(wk), voice(v){} void Set(); void Show() const; }; class SingingWaiter : public Singer,public Waiter { protected: void Data() const; void Get(); public: SingingWaiter(){} SingingWaiter(const std::string &s, long n, int p = 0, int v = other) : Worker(s, n), Waiter(s, n, p), Singer(s, n, v){} SingingWaiter(const Worker &wk, int p = 0, int v = other) : Worker(wk), Waiter(wk, p), Singer(wk, v){} SingingWaiter(const Waiter &wk, int v = other) : Worker(wk), Waiter(wk), Singer(wk, v){} SingingWaiter(const Singer &wk, int p = 0) : Worker(wk), Waiter(wk, p), Singer(wk){} void Set(); void Show() const; }; #endif /* work01_hpp */

.cpp

#include "work01.hpp" #include <iostream> using std::cout; using std::cin; using std::endl; // Worker Worker::~Worker() {} // protected void Worker::Data() const { cout << "Name: " << fullname << "\n"; cout << "Employee ID: " << id << "\n"; } void Worker::Get() { getline(cin, fullname); cout << "Enter worker's ID: "; cin >> id; while (cin.get()!='\n') continue; } // Waiter // protected void Waiter::Data() const { cout << "Panache rating: " << panache << endl; } void Waiter::Get() { cout << "Enter waiter's panache rating: "; cin >> panache; while (cin.get() != '\n') continue; } void Waiter::Set() { cout << "Enter waiter's name: "; Worker::Get(); Get(); } void Waiter::Show() const { cout << "Category: waiter\n"; Worker::Data(); Data(); } // Singer char * Singer::pv[] = {"other", "alto", "contralto", "soprano", "bass", "baritone", "tenor"}; void Singer::Data() const { cout << "Vocal range: " << pv[voice] << endl; } void Singer::Get() { cout << "Enter number for singer's vocal range:\n"; int i; for (i = 0; i < Vtypes; ++i) { cout << i << ": " << pv[i] << " "; if(i % 4 == 3) cout << endl; } if (i % 4 == 0) { cout << endl; } cin >> voice; while (cin.get() != '\n') { continue; } } void Singer::Set() { cout << "Enter singer's name: "; Worker::Get(); Get(); } void Singer::Show() const { cout << "Category: singer\n"; Worker::Data(); Data(); } // SingingWaiter void SingingWaiter::Data() const { Singer::Data(); Waiter::Data(); } void SingingWaiter::Get() { Singer::Get(); Waiter::Get(); } void SingingWaiter::Set() { cout << "Enter singing waiter's name: "; Worker::Get(); Get(); } void SingingWaiter::Show() const { cout << "Category: singing waiter\n"; Worker::Data(); Data(); }

虚基类使得从多个类派生出的对象只继承一个基类对象。本质上说,继承的Singer和Waiter对象共享一个Worker对象。 【注】禁止通过中间类自动传递给基类

4.模版类

#include <iostream> #include <string> #include <cctype> #include "stacktp.hpp" using std::cin; using std::cout; int main() { Stack<std::string> st; char ch; std::string po; cout << "Please enter A to add a purchase order,\n" << "P to proccess a PO, or Q to quit.\n"; while (cin >> ch && std::toupper(ch)!= 'Q') { while (cin.get() != '\n') continue; if (!std::isalpha(ch)) { cout << '\a'; continue; } switch (ch) { case 'A': case 'a': cout << "Enter a PO number to add: "; cin >> po; if (st.isfull()) cout << "Full!\n"; else st.push(po); break; case 'p': case 'P': if(st.isempty()) cout << "Empty\n"; else { st.pop(po); cout << "PO #" << po << " popped\n"; break; } } cout << "Please enter A to add a purchase order,\n" << "P to proccess a PO, or Q to quit.\n"; } cout << "Bye\n"; return 0; }

.hpp

#ifndef stacktp_hpp #define stacktp_hpp template <class Type> class Stack { private: enum{MAX = 10}; Type items[MAX]; int top; public: Stack(); bool isempty(); bool isfull(); bool push(const Type & item); bool pop(Type & item); }; template <class Type> Stack<Type>::Stack() { top = 0; } template <class Type> bool Stack<Type>::isempty() { return top == 0; } template <class Type> bool Stack<Type>::isfull() { return top == MAX; } template <class Type> bool Stack<Type>::push(const Type & item) { if (top < MAX) { items[top++] = item; return true; } else return false; } template <class Type> bool Stack<Type>::pop(Type & item) { if(top > 0){ item = items[--top]; return true; } else return false; } #endif /* stacktp_hpp */

5.指针栈

#include <iostream> #include <cstdlib> #include <ctime> #include "stacktp.hpp" const int Num = 10; int main() { std::srand(std::time(0)); std::cout << "Please enter stack size: "; int stacksize; // 确定栈的大小 std::cin >> stacksize; Stack<const char *> st(stacksize); // 生成 char*的指针栈 const char * in[Num] = { // 一组字符串常量 " 1: Hank Gilgamesh", " 2: Kiki Ishtar", " 3: Betty Rocker", " 4: Ian Flagranti", " 5: Wolfgang Kibble", " 6: Portia Koop", " 7: Joy Almondo", " 8: Xaverie Paprika", " 9: Juan Moore", " 10: Misha Mache", }; const char * out[Num]; // 用来存储pop出来的字符串 int processed = 0; int nextin = 0; while (processed < Num) { if(st.isempty()) st.push(in[nextin++]); else if (st.isfull()) st.pop(out[processed++]); else if(std::rand() % 2 && nextin < Num) st.push(in[nextin++]); else st.pop(out[processed++]); } for (int i = 0; i < Num; i++) { std::cout << out[i] << std::endl; } std::cout << "Bye\n"; return 0; } #ifndef stacktp_hpp #define stacktp_hpp template <class Type> class Stack { private: enum{SIZE = 10}; int stacksize; Type * items; int top; public: explicit Stack(int ss = SIZE); Stack(const Stack & st); ~Stack() {delete [] items;} bool isempty() { return top ==0; } bool isfull() { return top == stacksize; } bool push(const Type &item); bool pop(Type & item); Stack & operator=(const Stack & st); }; template <class Type> Stack<Type>::Stack(int ss) : stacksize(ss),top(0) { items = new Type[stacksize]; } template <class Type> Stack<Type>::Stack(const Stack & st) { stacksize = st.stacksize; top = st.top; items = new Type [stacksize]; for (int i = 0; i < top; i++) { items[i] = st.items[i]; } } template <class Type> bool Stack<Type>::push(const Type & item) { if(top < stacksize) { items[top++] = item; return true; } else return false; } template <class Type> bool Stack<Type>::pop(Type & item) { if(top > 0) { item = items[--top]; return true; } else return false; } template <class Type> Stack<Type> & Stack<Type>::operator=(const Stack<Type> &st) { if(this == &st) return *this; delete [] items; stacksize = st.stacksize; top = st.top; items = new Type [stacksize]; for(int i = 0; i < top; ++i) items[i] = st.items[i]; return *this; } #endif /* stacktp_hpp */

其实入栈的本质是新建一个指向该字符串的指针,出栈是把字符串的地址复制到out数组中。

5.成员模版

using std::cout; using std::endl; template <typename T> class beta { private: template <typename V> class hold; hold<T> q; // q 是基于T类型(beta类模版参数)hold对象 hold<int> n; // n 是基于int类型的hold对象 public: beta(T t, int i) : q(t), n(i){} template<typename U> U balab(U u, T t); void Show() const {q.show(); n.show();} }; template <typename T> template <typename V> class beta<T>::hold { private: V val; public: hold(V v = 0) : val(v){} void show() const { cout << val << endl; } V Value() const { return val; } }; template <typename T> template<typename U> U beta<T>::balab(U u, T t) { return (n.Value() + q.Value()) * u/t; } int main() { beta<double> guy(3.5, 3); cout << "T was set to double\n"; guy.Show(); cout << "V was set to T, which is double, then V was set to int\n"; cout << guy.balab(10, 2.3) << endl; cout << "U was set to int\n"; cout << guy.balab(10.0, 2.3) << endl; cout << "U was set to double\n"; cout << "Done\n"; return 0; }

6.模版类作为参数(套娃)

#include <iostream> template <class Type> class Stack { private: enum{MAX = 10}; Type items[MAX]; int top; public: Stack(); bool isempty(); bool isfull(); bool push(const Type & item); bool pop(Type & item); }; template <class Type> Stack<Type>::Stack() { top = 0; } template <class Type> bool Stack<Type>::isempty() { return top == 0; } template <class Type> bool Stack<Type>::isfull() { return top == MAX; } template <class Type> bool Stack<Type>::push(const Type & item) { if (top < MAX) { items[top++] = item; return true; } else return false; } template <class Type> bool Stack<Type>::pop(Type & item) { if(top > 0){ item = items[--top]; return true; } else return false; } template<template <typename T> class Thing> class Crab { private: Thing<int> s1; Thing<double> s2; // template <typename T> class 这句话是类型 // 也就意味着 Thing前面是个模版类 对应了下面的Stack // 也就意味着 Thing<int> s1 ==> Stack<int> s1; public: Crab(){} bool push(int a, double x) {return s1.push(a) && s2.push(x);} bool pop(int & a, double & x) {return s1.pop(a) && s2.pop(x);} }; int main() { using std::cout; using std::cin; using std::endl; Crab<Stack> nebula; int ni; double nb; cout << "Enter int double pairs, such as 4 3.5 (0 0 to end):\n"; while (cin >> ni >> nb && ni > 0 && nb > 0) { if (!nebula.push(ni, nb)) { break; } } while (nebula.pop(ni, nb)) { cout << ni << ", " << nb << endl; } cout << "Done.\n"; return 0; }

7.模版类与友元

#include<iostream> using std::cout; using std::endl; template <typename T> class HasFriend { private: T item; static int ct; public: HasFriend(const T & i) : item(i) { ct++; } ~HasFriend() { ct--; } friend void counts(); friend void reports(HasFriend<T> &); }; template <typename T> int HasFriend<T>::ct = 0; void counts() { cout << "int count: " << HasFriend<int>::ct << "; "; cout << "double count: " << HasFriend<double>::ct << endl; } void reports(HasFriend<int> &hf) { cout << "HasFriend<int>: " << hf.item << endl; } void reports(HasFriend<double> &hf) { cout << "HasFriend<double>: " << hf.item << endl; } int main() { cout << "No objects declared: "; counts(); HasFriend<int> hfi1(10); cout << "After hfi1 declared: "; counts(); HasFriend<int> hfi2(20); cout << "After hfi2 declared: "; counts(); HasFriend<double> hfdb(10.5); cout << "After hfi1 declared: "; counts(); reports(hfi1); reports(hfi2); reports(hfdb); return 0; }

友元函数约束模版

#include<iostream> using std::cout; using std::endl; template <typename T> void counts(); template <typename T> void reports(T &); template <typename TT> class HasFriendT { private: TT item; static int ct; public: HasFriendT(const TT & i) : item(i) { ct++; } ~HasFriendT() { ct--; } friend void counts<TT>(); friend void reports<>(HasFriendT<TT> &); // 等价 friend void reports<HasFriendT<TT> >(HasFriendT<TT> &); // 显然参数 是HasFriendT<TT>类型 所以可以不用加 // for exa. // HasFriendT<int> squack; // friend void counts<int>(); // friend void reports<>(HasFriendT<int> &); }; template <typename T> int HasFriendT<T>::ct = 0; template<typename T> void counts() { cout << "template size: " << sizeof(HasFriendT<T>) << "; "; cout << "template counts(): " << HasFriendT<T>::ct << endl; } template <typename T> void reports(T &hf) { cout << hf.item << endl; } int main() { counts<int>(); HasFriendT<int> hfi1(10); HasFriendT<int> hfi2(20); HasFriendT<double> hfdb(10.5); reports(hfi1); reports(hfi2); reports(hfdb); cout << "count<int>() output:\b"; counts<int>(); cout << "count<double>() output:\b"; counts<double>(); return 0; }
最新回复(0)