目录

1.包含对象成员的类

2.私有继承

3.各类继承方式:


1.包含对象成员的类


//class.h#pragma once#ifndef _CLASS_H_
#define _CLASS_H_#include<iostream>
#include<string> //使用string类
#include<valarray> //使用valarray类
using namespace std;class Student
{
private:typedef valarray<double> ArrayDb;  //typedef使得 ArrayDb为 valarray<double>类型的别名string name;ArrayDb scores;ostream& arr_out(ostream& os)const;
public:Student() :name("Null Student"), scores() { };explicit Student(const string& s) :name(s), scores() { };explicit Student(int n) :name("Nully"), scores(n) { };Student(const string& s, int n) :name(s), scores(n) { };Student(const string& s, const ArrayDb& a) :name(s), scores(a) { };Student(const char* str, const double& pd, int n) :name(str), scores(pd, n) { };~Student() { };double Average()const;const string& Name()const;double& operator[](int i);double operator[](int i)const;//friendfriend istream& operator>>(istream& is, Student& std);friend istream& getline(istream& is, Student& std); // 重载getline(cin,stringname)函数friend ostream& operator<<(ostream& os, const Student& std);
};#endif
#pragma once//fuc.cpp#include"class1.h"double Student::Average()const
{//调用了valarray类对象的size()和sum()函数if (scores.size() > 0){return scores.sum();}else{return 0;}
}const string& Student::Name()const
{return name;
}double& Student::operator[](int i)
{//调用了valarrayy类对象的operator[]()函数   valarray<double>::operator[]()return scores[i];
}double Student::operator[](int i)const
{return scores[i];
}ostream& Student::arr_out(ostream& os)const
{int i;int lim = scores.size();if (lim > 0){for (int i = 0; i < lim; i++){os << scores[i] << " ";if (i % 5 == 4){os << endl;}}if (i % 5 != 0){os << endl;}}else{os << " empty array";}return os;
}istream& operator>>(istream& is, Student& stu)
{is >> stu.name;return is;
}istream& getline(istream& is, Student& stu)
{getline(is, stu.name); //getline(cin,stringname)return is;
}ostream& operator<<(ostream& os, const Student& stu)
{os << "Scores for " << stu.name << ": \n";stu.arr_out(os);return os;
}//main.cpp#include"class1.h"void set(Student& sa, int n);
const int pupils = 3;
const int quizzes = 5;int main()
{//创建一个含有三个元素的数组,其中每个元素保存五个考试成绩(即调用scores(quizzes)构造函数创建了valarray<double>对象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() << endl;cout << "\n Result: \n";for (i = 0; i < pupils; i++){cout << endl << ada[i];cout << "average " << ada[i].Average() << endl;}cout << "Done" << endl;system("pause");return 0;
}void set(Student& sa, int n)
{cout << "Please enter the student's name: ";getline(cin, sa); //重载的getline函数,可以用与给类对象输入cout << "Please enter " << n << " quiz scores: \n";for (int i = 0; i < n; i++){//类中定义了成员函数operator[]().所以Student对象使用sa[i]时,即为调用sa中的scores[i]cin >> sa[i]; //sa[i]即为valarray<double>类scores对象的数组,cin>>sa[i]即为此数组赋值}while (cin.get() != '\n'){continue;}
}

知识点:

1.对于单参数的构造函数,最好加上explicit以防止其作为转换函数进行隐式转换。

eg:

explicit Student(const string& s) :name(s), scores() { };explicit Student(int n) :name("Nully"), scores(n) { };

2.valarray类 --  头文件#include<valarray>

1)用处:储存数据对象,并可以使用该类中含有的operaot[](),size(),sum(),max(),min()等函数对舒徐对象进行相应的处理。

2)相关构造函数:

eg:

Student(const string& s, const ArrayDb& a) :name(s), scores(a) { };//scores(a)即创建一个scores[a]的数组,其中共有a个元素Student(const char* str, const double& pd, int n) :name(str), scores(pd, n) { };//scores(pd,n)也是创建一个scores[a]的数组,同时为其中的a个元素均赋值为pd

3)语法:  valarray<typename> name

eg:

typedef valarray<double> ArrayDb;  //typedef使得 ArrayDb为 valarray<double>类型的别名
ArrayDb scores;
//等同于:
valarray<double> scores;

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

eg:

typedef valarray<double> ArrayDb;
ArrayDb scores;
string name;Student(const string& s, int n) :name(s), scores(n) { };//由于scores先声明,name后声明,即使在成员初始化的列表中是name在前,初始化过程中也是先初始化先声明的scores再初始化后声明的name。

2.私有继承

//class.h#pragma once#ifndef _CLASS_H_
#define _CLASS_H_#include<iostream>
#include<valarray> // valarray<typename> name
#include<string>using namespace std;class Student :private string, private valarray<double> //私有继承,继承string类和valarray<double>类
{
private:typedef valarray<double> ArrayDb;ostream& arr_out(ostream& os)const;
public://因为私有继承不显式的创建子对象,所以构造函数创建基类对象时在成员初始化部分只能直接调用基类的构造函数Student() :string("Null Student"), ArrayDb() { };explicit Student(const string& s) :string(s), ArrayDb() { };explicit Student(int n) :string("Nully"), ArrayDb(n) { };Student(const string& s, int n) :string(s), ArrayDb(n) { };Student(const string& s, const ArrayDb& a) :string(s), ArrayDb(a) { };Student(const char* str, const double& pd, int n) :string(str), ArrayDb(pd, n) { };~Student() { };double Average()const;const string& Name()const;double& operator[](int i);double operator[](int i)const;//friendfriend istream& operator>>(istream& is, Student& std);friend istream& getline(istream& is, Student& std); // 重载getline(cin,stringname)函数friend ostream& operator<<(ostream& os, const Student& std);
};#endif//fuc.cpp//私有继承通过使用类名和作用域解析运算符来调用基类的方法(没有显式的子对象成员,无法通过子对象成员来访问基类的方法)
//通过强制类型转换访问基类的对象,通过强制类型转换访问基类的友元函数#include"class.h"double Student::Average()const
{//调用了valarray类对象的size()和sum()函数if (ArrayDb::size() > 0){return ArrayDb::sum()/ArrayDb::size();}else{return 0;}
}const string& Student::Name()const
{return (const string&)*this;
}double& Student::operator[](int i)
{//调用了valarrayy类对象的operator[]()函数   valarray<double>::operator[]()return ArrayDb::operator[](i); //访问基类ArrayDb中的operator[]函数,并传入参数i
}double Student::operator[](int i)const
{return ArrayDb::operator[](i);
}ostream& Student::arr_out(ostream& os)const
{int i;int lim = ArrayDb::size();if (lim > 0){for (i = 0; i < lim; i++){os << ArrayDb::operator[](i) << " ";if (i % 5 == 4){os << endl;}}if (i % 5 != 0){os << endl;}}else{os << " empty array";}return os;
}istream& operator>>(istream& is, Student& stu)
{is >> (string &)stu; //为string类对象输入,而又没有显式的子成员对象,只能使用强制类型转换。return is;
}istream& getline(istream& is, Student& stu)
{getline(is, (string&)stu); //getline(cin,stringname)return is;
}ostream& operator<<(ostream& os, const Student& stu)
{os << "Scores for " << (string&)stu << ": \n";stu.arr_out(os);return os;
}//main.cpp#include"class.h"void set(Student& sa, int n);
const int pupils = 3;
const int quizzes = 5;int main()
{//创建一个含有三个元素的数组,其中每个元素保存五个考试成绩(即调用scores(quizzes)构造函数创建了valarray<double>对象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() << endl;cout << "\n Result: \n";for (i = 0; i < pupils; i++){cout << endl << ada[i];cout << "average " << ada[i].Average() << endl;}cout << "Done" << endl;system("pause");return 0;
}void set(Student& sa, int n)
{cout << "Please enter the student's name: ";getline(cin, sa); //重载的getline函数,可以用与给类对象输入cout << "Please enter " << n << " quiz scores: \n";for (int i = 0; i < n; i++){//类中定义了成员函数operator[]().所以Student对象使用sa[i]时,即为调用sa中的scores[i]cin >> sa[i]; //sa[i]即为valarray<double>类scores对象的数组,cin>>sa[i]即为此数组赋值}while (cin.get() != '\n'){continue;}
}

知识点:

1.私有继承private:基类的公有成员和保护成员都将成为派生类的私有成员(只可通过派生类的成员函数来访问)。

2.私有继承提供无名称的子对象成员,并通过构造函数的成员初始化调用相应的构造函数来进行初始化。(因此只能一个类只能创建一个子对象成员,否则会造成二义性)

3.私有继承通过使用类名和作用域解析运算符来调用基类的方法(没有显式的子对象成员,无法通过子对象成员来访问基类的方法)

4.访问基类对象:通过强制类型转换,将派生类对象强制转换成基类对象并进行相应的访问。

eg:

const string& Student::Name()const
{return (const string&)*this;
}//解析:this是指向调用对象的指针,*this则是调用对象本身,而通过(const string&)的强制转换,可以将调用对象*this转换成string类对象。

且强制类型转换需要配套: Student -> string , Student & -> string &...

5.访问基类的友元函数:类似与public继承中派生类访问基类友元函数的方法,通过强制类型转换改变参数的类型以匹配基类的友元函数。

eg:

ostream& operator<<(ostream& os, const Student& stu)
{os << "Scores for " << (string&)stu << ": \n"; stu.arr_out(os);return os;
}//调用的是基类的友元函数,通过强制类型转换参数类型以匹配基类的友元函数来完成

3.各类继承方式:

1.在使用保护继承(protected)和私有继承(private)时,若想让基类的方法在派生类的外面可用,可以通过包装,在派生类的方法中包含基类的方法:

eg:

double Student::sum() const
{return valarray<double>::sum();
}//保护继承和私有继承没有显式的子成员对象,只能通过类名+成员解析运算符来访问基类的方法

2. 通过using声明(类似于名称空间),来指出派生类可以使用的特定基类成员(在公有部分声明)。

eg:

class Student :private string , private valarray<double>
{public:using valarray<double>::max;using valarray<double>::min;}int main()
{Student s1;s1.max();s2.min();
}

1):使用using声明某基类函数后,派生类对象就可以像访问自己的成员函数一样访问该函数。

2):使用using声明函数并不是调用函数,所以在 classname:: 后只需要加上函数名,无需加上括号。

C++中的代码重用(1)相关推荐

  1. 【C++ Primer】第十四章 C++中的代码重用

    序:C++的一个主要目标是促进代码重用,其中包含公有继承.包含.使用私有或保护继承 一,包含对象成员的类        1)valarray类简介  #include <valarray> ...

  2. 一起来学C++:C++中的代码重用

    目录 14.1 包含对象成员的类 14.1.1 valarray类简介 14.1.2 Student类的设计 14.1.3 Student类示例 1.初始化被包含的对象 2.使用被包含对象的接口 3. ...

  3. 番外篇--C++中的代码重用

    实现代码重用的一些方法(这里并不是全部): 包含(组合.层次化):类包含另一个类的对象 使用私有继承或保护继承 以上两种方法都用于实现has-a关系,常用第一种方法 多重继承可以使多个基类派生出一个新 ...

  4. Go语言中的代码重用 - 继承还是组合?

    故事要从我在一个项目中,想要假装的专业一点而遇到的一个陷阱说起. 代码重用 在这个项目中,我们已经有了类似如下的代码: package main   import (     "fmt&qu ...

  5. cf16-1代码什么意思_CF中的代码重用-第一部分

    cf16-1代码什么意思 -posted by davidjmedlock: -由 davidjmedlock 发布 : Well, in about 7 hours I'm going to be ...

  6. 《C++ Primer Plus(第六版)》(30)(第十四章 C++中的代码重用 编程题答案)

    14.7 编程练习 1.Wine类有一个string类对象成员(参见第4章)和一个Pair对象(参见本章):其中前者用来存储葡萄酒的名称,而后者有2个valarry<int>对象(参见本章 ...

  7. C++ Primer Plus (第六版)编程练习记录(chapter14 C++中的代码重用)

    1.Wine类有一个string类对象成员(参见第4章)和一个Pair对象(参见本章):其中前者用于存储葡萄酒的名称,而后者有2个valarray对象(参见本章),这两个valarray对象分别保存了 ...

  8. java 重用性_提高Java代码重用性的三个方法

    三种修改现有代码提高其可重用性的方法,它们分别是:改写类的实例方法,把参数类型改成接口,选择最简单的参数接口类型. 措施一:改写类的实例方法 通过类继承实现代码重用不是精确的代码重用技术,因此它并不是 ...

  9. 攻防对抗形势下代码重用技术的演进

    ,基于代码重用的程序执行方式被广泛用于漏洞攻击中, 用来绕过代码不可执行.动态代码签名等安全机制.图 2从时间维度给出了代码重用攻击的演变历程. Fig. 2 Evolution of binary ...

最新文章

  1. SAP QM 检验批上的‘容器数’
  2. 2017年第八届蓝桥杯【C++省赛B组】
  3. nested exception is java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
  4. Vue的报错Echarts Cannot read property ‘init‘ of undefined
  5. 合法练习黑客技术?这15个网站也许可以帮到你
  6. RHCE 学习笔记(9) 网络管理
  7. 最IN的云原生架构,阿里云 Serverless 事件总线 EventBridge 重磅发布
  8. 用Flash模拟小车
  9. Windows操作系统的各进程的作用
  10. log4j.dtd_Eclipse log4j.xml –无法将log4j.dtd验证为XML定义
  11. 【ACL2020】五篇与文本理解相关的论文
  12. firefox 插件配置
  13. 34.Odoo产品分析 (四) – 工具板块(5) – 设备及联系人目录(1)
  14. Ubuntu 16.04下Linux驱动编写第一步
  15. cocos2d笔记 (3)cocos2d四个基本概念
  16. C#中用WinAPI调用外部程序
  17. SpringBoot整合Mybatis详细教程
  18. leetcode算法121.买卖股票的最好时机
  19. 基于rrweb框架对web 页面录制与回放
  20. struts2中常用Result总结

热门文章

  1. 永磁同步电机矢量控制(三)——电流环转速环 PI 参数整定
  2. sporadic偶发实时任务多核分区动态优先级EDF(或者DM)调度(以及可调度性分析)经典算法详解
  3. 使用 ava 和 jsdom 做前端测试
  4. AWS亚马逊云EC2搭建ginblog系统
  5. 艾赛克科技《RFID智能仓库管理系统》
  6. 金蝶K3采购暂估案例4商业模式单到冲回
  7. 处理piv数字照相图位移matlab程序,PIV数字图像测试技术及在中间包水模实验中的应用...
  8. vc中操作INI文件函数
  9. Cisco PT最新版下载路径
  10. 跟上节奏 大数据时代十大必备IT技能