①包含对象成员的类
1.介绍
学生可以表示成有姓名和一系列考试分数的人,我们基于此来开发Student类。对于姓名,我们可以采用string类来表示,对于考试分数,C++提供了一个根据string类设计表示数字数组的类,他就是valarray类。
2.valarray类介绍
valarray类是由头文件valarray支持的,是一个模板类,以便能够处理不同的数据类型。我们现在只需要知道模板类怎么应用,后边会讲到模板类的知识。
1.模板类声明对象
模板特性意味着声明对象时,必须指定具体的数据类型。valarray声明对象时,加上一对<>,并在其中包含所需的数据类型。
valarray<double> q_values;
valarray<int> weights;
2.类的构造函数
valarray<int> v1; 长度为0的int数组
valarray<double> v2(8); 长度为8的double空数组
valarray<int> v3(10,8); 长度为8的int数组,每个数字被设置为10
double gpa[5] ={3.1,3.2,4.1,3.5,3.8};
valarray<double> v4(gpa,4); 长度为为gpa前4个元素的数组
valarray<int> v1 = {1,2,3,4,5}; 初始化列表进行初始化
3.类的一些方法
operator[](); 访问数组元素
size();
sum();
max();
min();
还有很多其他方法,16章介绍
3.示例
①Student类设计
至此,我们已经确定了Student类的设计计划,设计方法有两种:
1.从string类 和valarray类派生出Student类,这里并不合适,因为学生与这两个类不是is-a的关系,这里的关系应该是has-a;学生有姓名和分数,而不是学生是姓名和分数。通常,用于建立has-a关系的C++技术是组合(包含),即创建一个包含其他类对象的类。
使用公有继承时,类可以继承接口,可能还有实现(基类的纯虚函数提供接口,但不提供实现)。而使用组合,类可以获得实现(方法都是在的,能不能用就不知道了),但不能获得接口(不能直接使用使用被包含的类的方法,除非通过成员函数来使用,然后在类外边通过该类的公有接口来间接使用方法)。
②Student类示例
#ifndef STUDENT_H_
#define STUDENT_H_
#include<string>
#include<valarray>
using std::string;
using std::valarray;
class Student
{
private:
typedef valarray<double> ArrayDb; //简化表示,student类外不能使用
string name;
ArrayDb scores;
std::ostream& arr_out(std::ostream& os) const; //valarray不能通过<<来输出,没有这样的实现,所以定义私有方法来处理这种任务
public:
Student():name("Null Student"),scores(){};
explicit Student(const string & na):name(na),scores(){};
explicit Student(int n):name("Null Student"),scores(n){};
Student(const string& na,int n) :name(na), scores(n) {};
Student(const char * str, const double *pd,int n) :name(str), scores(pd,n) {};
double Average()const;
const string& Name()const;
const double& operator[](int i)const;
double& operator[](int i);
~Student();
friend std::istream& operator>>(std::istream& is, Student& stu);
friend std::ostream& operator<<(std::ostream& os, Student& stu);
friend std::istream& getline(std::istream& is, Student& stu); //不是运算符重载,是重新定义函数,函数的重载
};
#endif
#include<iostream>
#include"student.h"
double Student::Average()const
{
if (scores.size() > 0)
return scores.sum() / scores.size();
else
return 0;
}
const string& Student::Name()const
{
return name;
}
const double& Student::operator[](int i) const
{
return scores[i];
}
double& Student::operator[](int i)
{
return scores[i];
}
Student::~Student(){};
//
std::istream& operator>>(std::istream& is, Student& stu)
{
is >> stu.name;
return is;
}
std::ostream& operator<<(std::ostream& os, Student& stu)
{
os << "name:" << stu.name << std::endl;
stu.arr_out(os);
return os;
}
std::istream& getline(std::istream& is, Student& stu)
{
getline(is, stu.name);
return is;
}
std::ostream& Student::arr_out(std::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)
os << std::endl;
}
if (i % 5 != 0)
os << std::endl;
}
else
os << "empty array ";
return os;
}
#include<iostream>
#include"student.h"
using std::cin;
using std::cout;
using std::endl;
void set(Student& sa, int n);
const int pupils = 3;
const int quizzes = 5;
int main()
{
Student ada[pupils] =
{
Student(quizzes),Student(quizzes),Student(quizzes)
};
int i;
for (int i = 0; i < pupils; ++i)
set(ada[i], quizzes);
cout << "\nStudent List:\n";
for (i = 0; i < pupils; i++)
{
cout << endl << ada[i];
cout << "average:" << ada[i].Average() << endl;
}
cout << "Done.\n";
return 0;
}
void set(Student& sa, int n)
{
cout << "Please enter the students' name:";
getline(cin, sa);
cout << "Please enter " << n << " quiz scores:\n";
for (int i = 0; i < n; i++)
cin >> sa[i];
while (cin.get() != '\n