C++包含对象的类(第十四章)

有时候在类中使用别的类的组件会方便很多。这就是has-a关系。比如学生类中有姓名和一系列考试成绩,姓名用string类对象表示,一系列成绩用valarray类对象表示。这就不是is-a关系了,这是student类中has string姓名和valarray成绩 关系。

valarray类简单介绍:

使用方法

  1. 声明方式:
    valarray<int> q_value 尖括号内说明这是个int类型模板类
  2. 使用对象:(构造函数)
double arr[5] = {3.1,3.5,3.8,3.9,4.0};
valarray<double> v1   一个size为0的double array
valarray<int> v2(8)   一个size为8的int array
valarray<int> v3(10,8)  一个size为8且每个值初始化为10的int array
valarray<double> v4(arr,4)     一个size为4,初始值为arr数组前四个
valarray<int> v5 = {20,32,1,2}  初始化列表
  1. 使用对象(基本方法)
    operator[]():访问各个元素
    size() : 返回包含的元素数
    sum() : 返回和
    max() , min()

Student类对象设计

  1. 关系has-a的类,类可以获得实现但不能继承接口。而is-a的类,获得接口是可以的。
    直观来说:is-a关系就是派生类可以使用基类的方法(virtual or not)(纯虚函数只提供接口不提供实现,就是派生类需要额外定义才能实现。接口就是抽象,比如上面的size()就是接口,而size()的功能被实现就是实现。)
  2. 比如string+string有意义,但student+student对象是没意义的。但有些借口对新类而言是有意义的,比如string的operator<()用到student类对象可以按姓名顺序排序,则可以定义Student::operator<(),然后在内部使用string::operator<()
类声明
#ifndef STUDENTC_H_
#define STUDENTC_H_
#include<iostream> 
#include<valarray>
#include<string>
class Student
{
    private:
        typedef std::valarray<double> AR;
        std::string name;
        AR scores;
        std::ostream& arr_out(std::ostream& os) const;
    public:
        Student() : name("No"),scores(){}
        explicit Student(const std::string& s):name(s),scores() {}
        explicit Student(int n): name("Jeff"),scores(n){}
        Student(const std::string& s,int n):name(s),scores(n){}
        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,const Student& s);
};
#endif

程序解析:

  1. explicit: 可以用一个参数调用的构造函数用作从参数类型到类类型的隐式转换函数,但这通常不是好主意,比如int到Student的转换是毫无意义的,所以用explicit避免隐式转换。
  2. 初始化被包含的对象:
    用成员初始化列表的方式,如果省略初始化列表,则C++将使用成员对象(既string和valarray)的默认构造函数。而用成员初始化列表name(str)则会调用string(const char*)。
  3. private那声明的函数也叫辅助函数,辅助函数可以用在类方法中。
源代码
#include"studentc.h"
using std::cout; 
std::ostream& Student::arr_out(std::ostream& os) const
{
    int i,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 scores ";
    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)
{
    for(int i=0;i<s.scores.size();i++)
        is>>s.scores[i];
    return is;
}

std::istream& getline(std::istream& is,Student& s)
{

    getline(is,s.name);
    return is;
}

std::ostream& operator<<(std::ostream& os,const Student& s)
{
    os<<"Scores for "<<s.name<<": ";
    s.arr_out(os);
    return os;
}

程序解析:

  1. 使用被包含对象的接口
    比如scores.size(),就是使用了valarray对象scores的接口size,但不能继承接口,既不能Student.size()。
  2. ostream& operator<<(ostream& os,const Student& s)
    首先s.name是一个string对象,则将调用函数
    ostream& operator<<(ostream& os,const string& s),该函数位于string类型中
  3. valarray也想有<<实现,但没有这种实现,所以可以定义一个私有辅助函数,然后在<<函数中使用辅助函数来实现功能。
主程序
#include"studentc.h"
using namespace std;
void set(Student& s,int n);
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(i=0;i<pupils;i++)
    {
        cout<<ada[i].Name()<<" ";
    }
    cout<<"\nStudent scores:\n";
    for(i=0;i<pupils;i++)
    {
        cout<<ada[i];
        cout<<"Average: "<<ada[i].average()<<endl;
    }
    cout<<"Done";
    return 0;
}

void set(Student& s,int n)
{
    cout<<"Enter the name: ";
    getline(cin,s);
    cout<<"Enter "<<n<<" scores: ";
    for(int i=0;i<n;i++)
        cin>>s[i];
    while(cin.get()!='\n')
        continue;
}

程序解析:

  1. 使用set函数来设置类对象值,在set中调用成员函数getline和>>函数
  2. 使用类数组,数组大小表示学生个数。
  3. cout<<ada[i].Name()<<" ";将调用的是string类中的<<,不是Student。
    cout<<ada[i]就是调用Student类的<<

关于类对象的调用,应该比较清楚了


image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345