c++代码重用—student(学习笔记)

第 14 章——C++中的代码重用

  • 包含对象成员的类

14.1.1 valarray简介

头文件valarray
支持的功能:

  1. 将数组中所用元素的值相加
  2. 找出最大最小值等操作

 

用valarray类声明一个对象

valarray < int > q_values;

valarray < double > weights;

使用构造函数的代码片段

valarray< double > gpa[5] = {3.4,5.6,7.8,5.3,1.2};

valarray < double > v1;

valarray < int > v2(8);// an array of 8 int elements

valarray < int > v3(10,8);//an array of 8 int elements;

                          //each set to 10;

valarray < double > v4(gpa,4)//an array of 4 double elements

                          //initialized to the first 4 elements of gpa;

 

14.1.2students类的设计

typedef std::valarray< double > ArrayDb;

  • 加入typedef的作用:在以后的代码中便可以使用表示ArrayDb

注意关键字explicit

explicit student(const std::string & s):name(s),scores(){}

explicit student(int n):name(),scores(n){}

上述代码使用explicit关闭隐式转换

 

  • 使用explicit来防止但参数数构造函数的隐式转换,根本原因:在编译阶段出现错误优于在运行阶段出现错误

初始化的顺序

  • 项目被初始化的顺序为他们被声明的顺序
    student(const char* str,const double* pd ,int n):scores(pd,n),name(str){}
    基于上述原则:name成员首先被初始化,因为在类的定义中他首先被声明,所以,在这个例子中初始化顺序并不重要,但是,如果如果一个成员的值作为另一个成员的初始化表达的一部分,初始化顺序就非常重要了。

函数实现

 1 #include

 2 using std::ostream;

 3 using std::endl;

 4 using std::cout;

 5 using std::istream;

 6 using std::string;

 7 

 8 //public methods

 9 double student::average()const

10 {

11     if(scores.size()>0)

12     {

13         return scores.sum()/scores.size();

14     }

15     else

16     {

17         return 0;

18     }

19 }

20 const string & student::Name()const

21 {

22     return name;

23 }

24 double & student::operator [](int i)

25 {

26     return scores[i];

27 }

28 

29 double student::operator [](int i)const

30 {

31     return scores[i];

32 }

33 //私有方法

34 ostream & student::arr_out(std::ostream & os)const

35 {

36     int i;

37     int lim=scores.size();

38     if(lim>0)

39     {

40         for(i=0;i<<<" ";

41             if(i%5==4)//一行5个元素

42                 os<<<<"empty array ";

43         return os;

44     }

45 }

46 //友元函数

47 istream & operator>>(istream & is,student& stu)

48 {

49     is>>stu.name;

50     return is;

51 }

52 //使用string友元函数

53 istream & getline(istream & is,student & stu)

54 {

55     is>>stu.name;

56     return is;

57 }

58 ostream & operator<<(ostream & os,const student& stu)

59 {

60     os<<"scores for: "<<<":\n";

61     //使用私有方法为了成绩的输出

62     stu.arr_out(os);

63     return os;

64 }

 

 

说明:

  • 问题一:使用被包含对象的接口

因为被包含对象的接口不是共有的,这里的接口,我的理解是被包含对象所属类的函数,那如何使用呢?我们可以通过类方法去使用它(在这里是studnet类),比如代码:

double student::average()const

{

	if(scores.size()>0)

	{

		return scores.sum()/scores.size();

	}

	else

	{

		return 0;

	}

}

student调用其作用域内的方法average(),average可以访问student的私用数据,也就是scores对象,scores是valarray的一个对象,自然可以调用它内部的方法

  1. size()
  2. sum()

 

  • 问题二:scores调用自身的类方法


double & student::operator [](int i)

{

	return scores[i];

}

scores[i]会直接调用valarray类中的重载方法:valarray<douoble>::operator[]()

  • 问题三:关于成员函数scores的输出

首先,我们可以先看成员函数name的输出,如下:

ostream & operator<<(ostream & os,const student& stu)

{

	os<<"scores for: "<< stu.name<<":\n";

	return os;

}

之所以可以这么做的原因是:stu.name是string的一个对象,这样会调用string内部的operator << ()重载函数我们是不也可以如法炮制scores呢?当然可以,除非valarray内也包含operator<<()函数,不巧的是,valarray没有这个函数

  • 定义私有辅助函数(类的私有数据里加入函数)
  • std::ostream & arr_out(std::ostream& os)const;
ostream & student::arr_out(std::ostream & os)const

{

	int i;

	int lim=scores.size();

	if(lim>0)

	{

		for(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;

	}

}

主函数

  • 包含3个对象的一个数组,每个对象包含5个成绩
 1 #include

 2 #include"student.h"

 3 

 4 using std::cin;

 5 using std::cout;

 6 using std::endl;

 7 void set(student & sa,int n);

 8 //两个常量

 9 const int pupils=3;

10 const int quizzes=5;

11 

12 

13 int main()

14 {

15     student ada[pupils]=

16     {student(quizzes),student(quizzes),student(quizzes)};

17 

18     int i;

19     for(i=0;i<pupils;++i) {="" set(ada[i],quizzes);="" }="" cout=""><<"\nstudents list\n";

20     for(i=0;i<pupils;++i) {="" cout=""><< ada[i].Name()<< endl;

21     }

22     cout<<"\nResults:";

23     for(i=0;i< pupils;++i)

24     {

25     cout<< endl<< ada[i];

26          cout<< "average: "<< ada[i].average()<< endl;

27     }

28     cout<< "Done.\n";

29     return 0;

30 }

31 

32 void set(student & sa,int n)

33 {

34     cout<< "请输入学生的名字: ";

35     getline(cin,sa);

36     cout<< "请输入"<< n << "个成绩:\n";

37     for(int i=0;i< n;i++)

38     {

39         cin>>sa[i];

40     }

41     while(cin.get()!='\n')

42         continue;

43 }

函数说明:

  • 问题一:getline(cin,sa);

注意:输入的时候不能有空格

    

  • 问题二:cin>>sa[i];
  • 在set函数的实现中,他会调用,第一条函数,但是,为什么返回类型是引用,这两个函数具体有什么区别呢?
    1 double & student::operator [](int i)
    
    2 {
    
    3     return scores[i];
    
    4 }
    
    5 
    
    6 double student::operator [](int i)const
    
    7 {
    
    8     return scores[i];
    
    9 }

     

 

你可能感兴趣的:(学习笔记)