对于姓名可以使用字符数组来表示,但这将限制姓名的长度。当然,还可以使用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) {…}

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

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

使用被包含对象的接口

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

C++_代码重用2-包含对象成员的类的更多相关文章

  1. has-a关系——包含对象成员的类

    #ifndef _STUDENT_H_ #define _STUDENT_H_ #include <iostream> #include <string> #include & ...

  2. C++_代码重用5-类模板

    如果两种类只是数据类型不同,而其他代码是相同的,与其编写新的类声明,不如编写一种泛型(独立于类型的)栈.然后将具体的类型作为参数传递给这个类.这样就可以使用通用的代码生成存储不同类型值的栈. 可以使用 ...

  3. C++_代码重用1-总览

    C++的主要目的是促进代码重用. 公有继承是实现这一目标的机制之一: 本身是另一个类的成员,这种方法称为包含.组合.层次化. 另一种方法是使用私有.保护继承. 通常包含.私有继承和保护继承用于实现ha ...

  4. C++_代码重用3-私有继承

    使用包含:易于理解,类声明中包含表示被包含类的显式命名对象,代码可以通过名称引用这些对象: 使用继承:将使关系更抽象,且继承会引起很多问题,尤其是从多个基类继承时. 私有继承所提供的特性确实比包含多. ...

  5. C++_代码重用4-多重继承

    继承使用时要注意,默认是私有派生.所以要公有派生时必须记得加关键字Public. MI(Multi Inheritance)会带来哪些问题?以及如何解决它们? 两个主要问题: 从两个不同的基类继承同名 ...

  6. C++——代码重用

    一.包含对象成员的类 接口和实现:使用公有继承时,类可以继承接口,可能还有实现(基类的纯虚函数提供接口,但不提供实现).获得接口是is-a关系的组成部分.而使用组合,类可以获得实现,但不能获得接口.不 ...

  7. 《C++ Primer Plus》第14章 C++中的代码重用 学习笔记

    C++提供了集中重用代码的手段.第13章介绍的共有继承能够建立is-a关系,这样派生类可以重用基类的代码.私有继承和保护继承也使得能够重用基类的代码,单建立的是has-a关系.使用私有继承时,积累的公 ...

  8. 【转载】C++对象成员与构造函数

    一个类的对象可以作为另一个类的数据成员,此时把该对象称为类的对象成员. 当一个类中出现对象成员时,该类的构造函数就要为对象成员初始化,对象成员的初始化必须在构造函数的初始化表中完成. 注意: 初始化对 ...

  9. 如何导出标准模板库(STL)类的实例化和包含STL类对象数据成员的类

    本文翻译自 https://support.microsoft.com/zh-cn/help/168958/how-to-export-an-instantiation-of-a-standard-t ...

随机推荐

  1. 06-Location详解之精准匹配

    之前nginx不是编译过吗?现在重新make install一下. 刚刚这个是我们新安装的.原始版的nginx,配置文件比较少,便于我们做调试. 试试精准匹配的概念. 匹配的是/.优先匹配这个最精准的 ...

  2. instanceof php

    instdnceof php5  的一个新成员 功能: 使用这个关键字可以确定一个对象是否是类的实例,是否是累的子类 ,还是实现了某个特定的接口. <?php class A{} class B ...

  3. DEDE 5.7中各函数所在的文件和位置

    /include/taglib/tag.lib.php 2 //function GetTags()/include/payment/yeepay.php 415 function log_resul ...

  4. 关于SO_LINGER选项的使用

    结论: linux开启SO_LINGER时,如果设置l_linger为非0, 不管是阻塞socket,非阻塞socket, 在这里都会发生阻塞, 而并不是UNP所讲到的( 非阻塞socket会立即返回 ...

  5. 通明讲JDBC(一)–认识JDBC

    本章记录了jdbc的简单使用方式! 0,jdbc的作用 1,jdbc入门准备工作 2,jdbc注册驱动 3,使用jdbc对数据库CRUD 0,jdbc的作用 与数据库建立连接.发送操作数据库的语句并处 ...

  6. GCC 常见参数配置

    博客转载自:https://www.cnblogs.com/zhangsir6/articles/2956798.html 简介gcc and g++现在是gnu中最主要和最流行的c & c+ ...

  7. OVS的初始配置

    1.去掉bridge模块,为下面用OVS的模块奠定基础 rmmod bridge .insmod datapath/linux/openvswitch_mod.ko .insmod datapath/ ...

  8. js-day

    1.克莱托指数 公式 :体重(kg) / (身高(m) * 身高(m)) < 20 : 偏瘦 > 20 <25 : 正常 > 25 : 偏旁 步骤: 1.输入体重(weight ...

  9. Mac OS X 下android环境搭建

    安装jdk6.0版本以支持eclipse的安装 安装eclipse 安装jdk8.0版本,实际开发中用到的jdk 配置java环境变量 打开shell命令窗口(终端) 检测输入java -versio ...

  10. wpf 依赖属性注册解释

    这个解释的很明白了 http://www.cnblogs.com/xiongpq/archive/2010/06/29/1767905.html