zoukankan      html  css  js  c++  java
  • C++_代码重用2-包含对象成员的类

    对于姓名可以使用字符数组来表示,但这将限制姓名的长度。当然,还可以使用char指针和动态内存分配,但这要求提供大量的支持代码。有一个好的方法就是使用一个他人开发好的类的对象来表示。如果C++库提供了合适的类,实现起来将更简单。C++库确实提供了一个这样的类,它就是valarray。

    valarray类简介

           模板类在使用时需要指定具体数据类型。

           valarray<int>  q_values; //an array of int

           valarray<double> weights; //an array of double

          

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

           valarray<double> v1; //double类型的空数组

           valarray<int> v2(8);  //长度为8的整型元素。

           valarray<int> v3(10,8);  //长度为8的整型元素,每个长度为10。

           valarray<double> v4(gpa,4)  //使用gpa数组的前4个元素给v4赋值。

           valarray<int>v5 = {20,32,17,9};  //C++11

     

           类的一些方法:

           operator[]()  能够访问各个元素;

           size()  返回包含的元素数

           xum()  返回所有元素的总和

           max()  返回最大的元素

           min()  返回最小的元素

    Student类的设计

    class Student

    {

    private:

           string name;

           valarray<double> scores;

    };

    Student类获得了其成员对象的实现,但没有继承接口。这意味着Student类成员函数可以使用string和valarray类的公有接口来访问和修改name和scores对象。但在类外不能这样做,而只能通过Student类的公有接口访问name和scores。

     

    接口与实现的概念

    获得接口是is-a关系的组成部分。

    而使用组合,类可以获得实现,但不能获得接口。不继承接口是has-a关系的组成部分。

     

    对于has-a关系而言,类对象不能获得包含对象的接口是一件好事。

    Student类示例

    //studentc.h--defining a Student class using containment

    #ifndef STUDENTC_H_

    #define STUDENTC_H_

     

    #include <iostream>

    #include<string>

    #include<valarray>

     

    class Student

    {

    private:

           typedef std::valarray<double> ArrayDb;

           std::string name;

           ArrayDb scores;

           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(s), scores() {}

           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

           friend std::istream & operator>>(std::istream & is, Student & stu);

           friend std::istream & getline(std::istream & is, Student & stu);

          

           friend std::ostream & operator<<(std::ostream & os, const Student & stu);

    }

     

    #endif

    注意:如果不使用explicit,可以编写如下的代码:

    Student doh(“Homer”,10);

    doh = 5;  //粗心的程序员键入了doh而不是doh[0],这会导致使用构造函数调用Student(5)将5替换为一个临时Student对象,并使用“Nully”来设置成员name的值。因此赋值操作将使用临时对象来替换原来doh值,使用了explicit之后,编译器将认为上述运算符是错误的。

     

    C++和约束

    使用explict防止但参数构造函数的隐式转换,使用const限制方法修改数据。这样做的根本原因是:在编译阶段出现错误优于在运行阶段出现错误。

     

    初始化被包含的对象

    构造函数使用您熟悉的成员初始化列表来初始化name和score成员对象。

    Queue::Queue(int qs) : qsize(qs) {…}

    还可以使用成员初始化列表来初始化派生对象的基类部分:

    hasDMA::hasDMA(): baseDMA(hs) {…}

     

    初始化列表中的每一项都调用与之匹配的构造函数。

     

    初始化顺序:当初始化列表包含多个项目时,这些项目被初始化的顺序为它们被声明的顺序,而不是它们在初始化列表中的顺序。

     

    使用被包含对象的接口

    被包含对象的接口不是公有的,但可以在类方法中使用它。

  • 相关阅读:
    2013年第四届蓝桥杯C/C++ A组国赛 —— 第三题:埃及分数
    单链表————链表
    单链表————顺序表
    跳水板
    平衡二叉搜索树(最小高度树)
    删除字符串中的所有相邻重复项
    用两个栈实现队列
    删除最外层的括号
    合并两个有序链表
    C++ cout格式化输出(输出格式)完全攻略
  • 原文地址:https://www.cnblogs.com/grooovvve/p/10422232.html
Copyright © 2011-2022 走看看