C++_primer_plus学习笔记 第14章 C++中的代码重用

本章内容包括:

  • has-a关系
  • 包含对象成员的类
  • 模板类和valarray
  • 私有和保护继承
  • 多重继承
  • 虚基类
  • 创建类模板
  • 使用类模板
  • 模板具体化

14.1 包含对象成员的类

14.1.1 valarray类简介(数值数组模板类)

valarray<int> q_values;             //int数组

valarray<double> weights;        //double数组

回顾:

vector<double> vd(n);

array<int, 5> ai;

使用构造函数的例子:

double gpa[5] = { 3.1, 3.5, 3.8, 2.9, 3.3 };

valarray<double> v1;                        //长度为0的空数组

valarray<int> v2(8);                          //指定长度的空数组

valarray<int> v3(10, 8);                    //所有元素(8)被初始化为指定值(10)的数组

valarray<double> v4(gpa, 4);           //用常规数组(gpa)的值(前4个)进行初始化

valarray<int> v5 = { 20, 32, 17, 9 };  //初始化列表

 valarray类方法:

  • operator[]()
  • size()
  • sum()
  • max()
  • min()

14.1.2 Student类设计

is-a模型:水果->香蕉

has-a模型:午餐->香蕉

student类的成员函数可以通过name和score使用string类和valarray类的公有方法,来操作string类的对象name和valarray类的对象score,但并不是基类和派生的继承关系。

一个类对象通过另一个类对象调用另一个类的公有方法

14.1.3 Student类示例

//程序清单 14.1 studentc.h
#pragma once
#ifndef STUDENTC_H_
#define STUDENTC_H_

#include <iostream>
#include <string>
#include <valarray>

using namespace std;

class Student
{
private:
	//typedef valarray<double> ArrayDb;
	using ArrayDb = valarray<double>;    //放私有意味着只可以在student类中使用ArrDb
	string name;
	ArrayDb scores;
	ostream& arr_out(ostream& os) const;

public:
	Student() : name("Null Student"), scores() {}
    //                                长度为0的double空数组
	//转换函数
	explicit Student(const string& s) : name(s), scores() {}
	//string类型显式转换为student类类型,禁止隐式转换
	explicit Student(int n) : name("Nully"), scores(n) {}
	//int类型显式转换为student类类型,包含长度为n的double空数组
	Student(const string& s, int n) : name(s), scores(n) {}
	//string和int类型的转换为student类类型
	Student(const string& s, const ArrayDb& a) : name(s), scores(a) {}
	Student(const string& s, const double* pd, int n) : name(s), scores(pd, n) {}
	~Student(){}

	double Average() const;
	const string& Name() const { return name; }					//显示名称
	double& operator[](int i) { return scores[i]; }				//修改某一门成绩
	double operator[](int i) const { return scores[i]; }		//只读赋值

	friend istream& operator>>(istream& is, Student& stu);
	friend istream& getline(istream& is, Student& stu);
	friend ostream& operator<<(ostream& os, const Student& stu);

};

#endif // !STUDENTC_H_

 对于继承的对象,构造函数在成员初始化列表中使用类名来调用特定的基类构造函数:

hasDMA::hasDMA(const hasDMA & hs) : baseDMA(hs) {...}

对于成员对象,构造函数则使用成员名:

Student(const char * str, const double * pd, int n) : name(str), score(pd, n) {}

//程序清单 14.2
#include "studentc.h"

double Student::Average() const
{
	if (scores.size() > 0)    //元素个数
		return scores.sum() / scores.size();
	else
		return 0;
}

istream& operator>>(istream& is, Student& stu)
{
	is >> stu.name;
	return is;
}
istream& getline(istream& is, Student& stu)
{
	getline(is, stu.name);
	return is;
}
ostream& operator<<(ostream& os, const Student& stu)
{
	os << "Scores for " << stu.name << ":\n";
	stu.arr_out(os);
	return os;
}

ostream& Student::arr_out(ostream& os) const
{
	int i;
	int lim = scores.size();
	if (lim > 0)
	{
		for (i = 0; i < lim; i++)
		{
			os << scores[i] << " ";
			if (i % 5 == 4)		//每行5个
				os << endl;
		}
		if (i % 5 != 0)
			os << endl;			//显示光标换行
	}
	else
		os << "Empty array!";
	return os;
}
//程序清单 14.3
#include <iostream>
#include "studentc.h"

const int pupils = 3;	//3个学士
const int quizzes = 5;	//5门成绩
void set(Student& sa, int n);

int main(void)
{
	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 (i = 0; i < pupils; i++)
		cout << ada[i].Name() << endl;
	cout << "\nResult:\n";
	for ( i = 0; i < pupils; i++)
	{
		cout << ada[i];
		cout << "average: " << ada[i].Average() << endl << endl;
	}

	return 0;
}

void set(Student& sa, int n)
{
	cout << "Enter the student's name: ";
	//调用friend istream& getline(istream& is, Student& stu)
	getline(cin, sa);
	cout << "Enter " << n << " quiz scores:\n";
	for (int i = 0; i < n; i++)
		//调用double& operator[](int n);
		cin >> sa[i];
	while (cin.get() != '\n')
		continue;
}

14.2 私有继承

  • 包含将对象作为一个命名的成员对象添加到类中
  • 私有继承将对象作为一个未被命名的继承对象添加到类中

14.2.1 Student类新版本

  •  包含版本提供两个被显式命名的对象成员
  • 私有继承提供两个无名称的隐式对象成员
//程序清单 14.4
#pragma once
#ifndef STUDENTI_H_
#define STUDENTI_H_

#include <iostream>
#include <string>
#include <valarray>

using namespace std;

class Student : private string, private valarray<double>
//私有继承使用关键字private,多个基类的继承称为多重继承
{
private:
	typedef valarray<double> ArrayDb;
	//using ArrayDb = valarray<double>;
	ostream& arr_out(ostream& os) const;

public:
    //基类类名代替成员名
	Student() : string("Null Student"), ArrayDb() {}
	//转换函数
	explicit Student(const string& s) : string(s), ArrayDb() {}
	//string类型显式转换为student类类型,禁止隐式转换
	explicit Student(int n) : string("Nully"), ArrayDb(n) {}
	//int类型显式转换为student类类型,包含长度为n的double空数组
	Student(const string& s, int n) : string(s), ArrayDb(n) {}
	//string和int类型的转换为student类类型
	Student(const string& s, const ArrayDb& a) : string(s), ArrayDb(a) {}
	Student(const string& s, const double* pd, int n) : string(s), ArrayDb(pd, n) {}
	~Student() {}

	double Average() const;
	const string& Name() const { return (const string&) *this; }					
    //显示名称
	double& operator[](int i) { return ArrayDb::operator[](i); }				
    //修改某一门成绩
	double operator[](int i) const { return ArrayDb::operator[](i); }		
    //只读赋值

	friend istream& operator>>(istream& is, Student& stu);
	friend istream& getline(istream& is, Student& stu);
	friend ostream& operator<<(ostream& os, const Student& stu);

	using valarray<double>::max;
};

#endif // !STUDENTI_H_

1.类名代替成员名 

//包含
Student(const string& s, const double* pd, int n) : name(s), scores(pd, n) {}
//私有
Student(const string& s, const double* pd, int n) : string(s), ArrayDb(pd, n) {}

2.访问基类方法:类名+::

//包含
double Student::Average() const
{
	if (scores.size() > 0)    //元素个数
		return scores.sum() / scores.size();
	else
		return 0;
}
//私有
double Student::Average() const
{
	if (ArrDb::size() > 0)    //元素个数
		return ArrDb::sum() / scores.size();
	else
		return 0;
}

3.访问基类对象:强制类型转换


                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值