1.valarray类简介
valarray类是一个处理数值的类,它支持诸如将数组中所有元素的值相加以及在数组中找到最大和最小的值等操作。valarray被定义成了一个模板类,能够处理不同的数据类型,下面是valarray类的用法介绍:
//valarray类声明对象的方式
#include
valarray<int> q_values;
valarray<double> weights;
//valarray构造函数的用法
int gba[5] = {
5,4,3,2,1};
valarray<int> i_value; //定义了一个int型数组,size为0
valarray<int> i_value2(8); //定义一个有8个元素的数组
valarray<int> i_value3(10,8); //定义一个有8个元素的数组,每个元素的值都被初始化为10
valarray<int> i_value4(gba,4); //定义一个有4个元素的数组,元素被初始化为gba数组的前四个元素
//valarray的方法
operator[]() //访问各个元素
size() //返回包含的元素数
sum() //返回所有元素的总和
max() //返回最大的元素
min() //返回最小的元素
2.代码重用的方式----student类的设计
我们要设计的student类要包含学生的名字和成绩,学生的名字我们想使用string类,而成绩使用我们刚刚介绍的valarray类,现在我们创建的类需要包含着两个类的内容,我们要考虑是否要使用之前学过的公有继承,显然这是不合适的,虽然C++允许多重公有继承,但是需要注意的是,这里并不满足is-a的条件,学生既不是姓名,也不是考试成绩,这里的关系是has-a的关系,也就是包含关系,学生拥有姓名和考试成绩,所以这里要使用C++的一项别的技术,组合,也就是创建一个包含其他类对象的类。student类的声明方式如下:
class Student
{
private:
string name;
valarray<double> scores;
...
};
注意:上述类将数据成员声明为私有的,这意味着Student内部的成员函数可以使用string和valarray
//利用组合的方式设计的students类
//student.h
#ifndef STUDENT_H_
#define STUDENT_H_
#include
#include
//用于简化代码
typedef valarray<double> ArrayD
class Student
{
private:
string name;
ArrayD scores;
//由于valarray类中并没有重载<<运算符,所以定义私有方法
//以保证友元函数中重载的<<运算符函数可以看起来更加简洁
std::ostream & arr_out(std::ostream & os) const;
public:
Student() : name("Null Student"),score() {
}
//explicit关键字防止了隐式的转换
explicit Student(const std::string & s) : name(s),scores() {
}
explicit Student(int n) : name("Nully"),socres(n) {
}
Student(const std::string & s,int n) : name(s),scores(n){
}
Student(const std::string & s,const ArrayD & a) : name(s),scores(a){
}
Student(const char * str,const double * d, int n): name(str),scores(d,n){
}
~Student(){
}
double Average() const;
const std::string & Name() const;
//下述是对于[]运算符的重载,[]运算符的重载必须是在类成员中重载
//不能使用友元函数,之所以使用重载
//是因为一个是用于const类型,而另一个使用的是引用类型
//如果只有第一种的话,没有办法给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,const Student & s);
};
3.私有继承
私有继承的特点:基类的公有成员和保护成员豆浆称为派生类的私有成员。也就是基类方法不会称为派生对象公有接口的一部分,但可以在派生类的成员函数中使用他们。
私有继承将对象作为一个未被命名的继承对象添加到类中,我们用子对象来表示通过继承或者包含添加的对象。
私有继承提供的特性与包含相同:获得实现,但是不获得接口。
4.使用私有继承来实现Student类
//如何声明一个私有继承----private
//注意:不使用关键字的情况下,也会默认使用私有继承(默认关键字为【private】)
class Student : private std::string, private std::valarray<double>
{
public:
...
};
//对于包含来说,使用的构造函数是通过成员名来初始化列表的
Student(const char * str, const double * pd, int n):name(str),scores(pd,n){
}
//对于私有继承来说,使用类名而非成员名标识构造函数
Student(const char * str, const double * pd, int n):std::string(str),std::valarray<double>(pd,n){
}
//利用组合的方式设计的students类
//student.h
#ifndef STUDENT_H_
#define STUDENT_H_
#include
#include
//用于简化代码
class Student : private std::string, private std::valarray<double>
{
private:
typedef valarray<double> ArrayD
//由于valarray类中并没有重载<<运算符,所以定义私有方法
//以保证友元函数中重载的<<运算符函数可以看起来更加简洁
std::ostream & arr_out(std::ostream & os) const;
public:
Student() : std::string("Null Student"),score() {
}
//explicit关键字防止了隐式的转换
explicit Student(const std::string & s) : std::string(s),ArrayD() {
}
explicit Student(int n) : std::string("Nully"),ArrayD(n) {
}
Student(const std::string & s,int n) : std::string(s),ArrayD(n){
}
Student(const std::string & s,const ArrayD & a) : std::string(s)