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) {…}

     

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

     

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

     

    使用被包含对象的接口

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

  • 相关阅读:
    ThinkPHP 3.2.2 实现持久登录 ( 记住我 )
    Java实现 LeetCode 20 有效的括号
    Java实现 LeetCode 20 有效的括号
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 17 电话号码的字母组合
  • 原文地址:https://www.cnblogs.com/grooovvve/p/10422232.html
Copyright © 2011-2022 走看看