C++学习总结 19 -- 继承

小记:静默如初,安之若素

继承(Inheritance)

1. 继承的概念//了解
通过一种机制来表达类型之间共性和特征的方式,利用已有的数据类型定义新的数据类性,这种机制就是继承。

eg:
	人类:姓名,年龄,吃饭,睡觉
	学生类:姓名,年龄,吃饭,睡觉,学号,学习
	教师类:姓名,年龄,吃饭,睡觉,工资,授课
	----------------------------------
	人类:姓名,年龄,吃饭,睡觉
	学生类继承人类:学号,学习
	教师类继承人类:工资,授课
	----------------------------------
	      人类(基类)
	      /  \
	  学生类  教师类(派生类,子类)
	  注:基类派生子类, 子类继承基类

2. 继承的语法

class 子类:继承方式 基类,...
{
};
继承方式:
--public:公有继承
--protected:保护继承
--private:私有继承
eg:
class Human{吃饭,年龄,睡觉,吃饭};
class Student:public Human
{
 //学生继承了人类
 //人类中的成员在当前学生类就可以直接适用
};

示例:

 1 #include <iostream>
  2 using namespace std;
  3 
  4 //人类(基类)
  5 class Human
  6 {
  7 public:
  8   Human(const string& name, int age):m_name(name), m_age(age){}
  9   
 10   void eat(const string & food)
 11   { 
 12     cout << "Food : " << food << endl;
 13   }
 14   
 15   void sleep(int time)
 16   { 
 17     cout << "Sleep time : " << time << endl;
 18   }
 19 
 20 protected://保护型成员可以在子类中被访问
 21   string m_name;
 22   int m_age;
 23 };
 24 
 25 //学生类(人类的一个子类)
 26 class Student:public Human
 27 {
 28 public:
 29  //说明从基类中继承过来的成员初始化方式
 30   Student(const string &name, int age, int num)
 31     :Human(name, age), m_num(num){}
 32 
 33   void learn(const string& course)
 34   {
 35     cout << "learn lesson : " << course << endl;
 36   }
 37   
 38   void who(void)
 39   {
 40     cout << "my name : " << m_name << " , age : "<< m_age << " ,num : " << m_num << endl;
 41   }
 42 private:
 43   int m_num;
 44 };
 45 //教师类(人类的另一个子类)
 46 class Teacher:public Human
 47 {
 48 public:
 49   Teacher(const string &name, int age, float salary)
 50     :Human(name, age), m_salary(salary){}
 51     
 52   void teach(const string &course)
 53   {
 54     cout <<"teach lesson : " << course << endl;
 55   }
 56   void who(void)
 57   {
 58     cout << "my name : " <<m_name << ", age : " << m_age << " ,salary : " << m_salary << endl;
 59   }
 60 private:
 61   float m_salary;
 62 };
 63 
 64 
 65 int main(int argc, char *argv[])
 66 {
 67   Student s("red", 35, 10011);
 68   s.who();
 69   s.eat("noodle");
 70   s.sleep(8);
 71   s.learn("Chinese");
 72 
 73   Teacher t("red2", 33, 8000.8);
 74   t.who();
 75   t.eat("rice");
 76   t.sleep(7);
 77   t.teach("English");
 78 
 79   return 0;
 80 }

3. 公有继承的特性(public)
1)子类对象会继承基类属性的行为,通过子类对象可以访问基类中的成员,如同是基类对象在访问它们一样。
注:子对象中包含基类的部分成为”基类子对象“:
2)向上造型:
将子类类型的指针或引用转换为基类类型的指针或引用,只能在公有继承中实现.
注:这种操作性缩小的类型的转换,在编译器看来是安全的可以直接隐式完成转换

     基类
      ↑
     子类
   注:转的是指针和引用,不改变内存上的任何数据
   eg:
   class Base{...};//基类
   class Derived:public Base {...};//子类
   void func1(Base&){}
   void func2(Base*){}
   int main()
   {
     Devived d;
     func1(d);//向上造型
     func2(&d);//向上造型
   }

3)向下造型
将基类类型的指针或引用转换为子类类型的指针或引用
注:这种操作性缩小的类型的转换,在编译器看来是危险的不可以直接隐式转换,但可以通过显示转换

     基类
      ↓
     子类
   注:转的是指针和引用,不改变内存上的任何数据

4)子类继承基类的成员
–》在子类中,可以直接访问基类中的共有或保护成员,如同它们是子类自己的成员变量一般;
–》基类中的私有成员子类也可以继承过来,但是会收到访问控制属性的限制,无法直接访问;如果子类需要访问基类中的私有成员,可以通过基类提供的共有或保护的接口函数来间接访问。
–》基类的构造函数和析构函数,子类是无法继承的,但是可以在子类的构造函数使用初始化表显式指明基类部分的初始化方式。

 1 #include <iostream>
  2 using namespace std;
  3 
  4 //人类(基类)
  5 class Human
  6 {
  7 public:
  8   Human(const string& name, int age):m_name(name), m_age(age),m_id(1234){}
  9 
 10   void eat(const string & food)
 11   {
 12     cout << "Food : " << food << endl;
 13   }
 14 
 15   void sleep(int time)
 16   {
 17     cout << "Sleep time : " << time << endl;
 18   }
 19 
 20 protected://保护型成员可以在子类中被访问
 21   string m_name;
 22   int m_age;
 23   //私有成员子类中无法直接访问,但是可以提供保护的借口函数来间接访问
 24   const int& getId(void)
 25   {
 26     return m_id;
 27   }
 28 private:
 29   int m_id;
 30 };
 31 
 32 //学生类(人类的一个子类)
 33 class Student:public Human
 34 {
 35 public:
 36  //Human(...) : 说明从基类中继承过来的成员初始化方式
 37   Student(const string &name, int age, int num)
 38     :Human(name, age), m_num(num){}
 39 
 40   void learn(const string& course)
 41   {
 42     cout << "learn lesson : " << course << endl;
 43   }
 44 
 45   void who(void)
 46   {
 47     cout << "my name : " << m_name << " , age : "<< m_age << " ,num : " << m_num << endl;
 48     cout << "ID num : " << getId() << endl;
 49   }
 50 private:
 51   int m_num;
 52 };
 53 //教师类(人类的另一个子类)
 54 class Teacher:public Human
 55 {
 56 public:
 57   Teacher(const string &name, int age, float salary)
 58     :Human(name, age), m_salary(salary){}
 59 
 60   void teach(const string &course)
 61   {
 62     cout <<"teach lesson : " << course << endl;
 63   }
 64   void who(void)
 65   {
 66     cout << "my name : " <<m_name << ", age : " << m_age << " ,salary : " << m_salary << endl;
 67   }
 68 private:
 69   float m_salary;
 70 };
 71 
 72 
 73 int main(int argc, char *argv[])
 74 {
 75   Student s("red", 35, 10011);
 76   s.who();
 77   s.eat("noodle");
 78   s.sleep(8);
 79   s.learn("Chinese");
 80 
 81   Teacher t("red2", 33, 8000.8);
 82   t.who();
 83   t.eat("rice");
 84   t.sleep(7);
 85   t.teach("English");
 86 
 87   //Student*--> Human*::向上造型
 88   Human *ph = &s;
 89   ph->eat("apple");
 90   ph->sleep(16);
 91 
 92 
 93   //Human*-->Student*::向下造型
 94   Student *ps = static_cast<Student*>(ph);//不能隐式转换,但可以显示转换
 95   ps->who();
 96 
 97   Human h("red3", 22);
 98   //Human*-->Student:向下造型
 99   Student *ps2 = static_cast<Student*>(&h);
100   ps2->who();
101 
102 
103   return 0;
104 }
       

5)子类隐藏基类的成员
–》如果子类和基类中有同名的成员函数(变量),因为作用域不同,不会有重载关系,而是一种隐藏关系。如果需要访问基类中隐藏的成员函数,可以通过“基类::”显式指明。

  1 #include <iostream>
  2 using namespace std;
  3 
  4 class Base
  5 {
  6 public:
  7   void foo(void)
  8   {
  9     cout << "Base::foo" << endl;
 10   }
 11 };
 12 
 13 
 14 class Derived:public Base
 15 {
 16 public:
 17   void foo(int i)
 18   {
 19     cout << "Derived::foo" << endl;
 20   }
 21 };
 22 
 23 int main(int argc, char *argv[])
 24 {
 25   Derived d;
 26   //加作用域限定符
 27   d.Base::foo();
 28   d.foo(10);
 29  
 30   return 0;
 31 }

4. 继承方式和访问控制属性
1)访问控制限定符:影响访问该成员的位置

访问控制限定符  访问控制属性  内部访问  子类访问  外部访问  友元访问
public        公有属性       ok      ok       ok      ok
protected     保护成员       ok      ok       no      ok
private       私有成员       ok      no       no      ok

2)基类的继承方式:影响通过子类访问基类中的成员的可访问性

基类中的    在公有子类中变成    在保护子类中变成   在私有子类中变成
公有成员       公有成员          保护成员          私有成员
保护成员       保护成员          保护成员          私有成员
私有成员       私有成员          私有成员          私有成员

注:向上造型语法在保护继承和私有继承中不再适用

 1 #include <iostream>
  2 using namespace std;
  3 
  4 class A
  5 {
  6 public:
  7   int m_public;
  8 protected:
  9   int m_protected;
 10 private:
 11   int m_private;
 12 };
 13 
 14 class B:public A{};
 15 class C:protected A{};
 16 class D:private A{};
 17 
 18 //子类的子类
 19 //X公有继承B,B公有继承了A中的成员,
 20 //等价于X保护继承了A的成员,从而导致了X能访问A中的除私有成员以外的所有成员
 21 class X:public B
 22 { 
 23   void func(void)
 24   {
 25     m_public = 10;
 26     m_protected = 10;
 27     //m_private = 10; error
 28   }
 29 };
 30 
 31 //子类的子类
 32 //Y公有继承C,C保护继承了A中的成员,
 33 //等价于Y保护继承了A的成员,从而导致了Y能访问A中的除私有成员以外的所有成员
 34 class Y:public C
 35 { 
 36   void func(void)
 37   { 
 38     m_public = 10;
 39     m_protected = 10;
 40     //m_private = 10; error
 41   }
 42 };
 43 
 44 //子类的子类,Z公有继承D,D私有继承了A中的成员,
 45 //等价于z私有继承了A的成员,从而导致了Z不能访问A中的所有成员
 46 class Z:public D
 47 { 
 48   void func(void)
 49   { 
 50     //m_public = 10;
 51     //m_protected = 10;
 52     //m_private = 10; 
 53   }
 54 };
 56 int main(int argc, char *argv[])
 57 { 
 58   B b;
 59   b.m_public = 10;
 60   //b.m_protected = 10; //error
 61   //b.m_private = 10; //error
 62 
 63   C c;
 64   //c.m_public = 10; //error
 65   //c.m_protected = 10; //error
 66   //c.m_private = 10; //error
 67 
 68   D d;
 69   //d.m_public = 10; //error
 70   //d.m_protected = 10; //error
 71   //d.m_protected = 10; //error
 72 
 73   return 0;
 74 }

5. 子类的构造函数
1)如果子类构造函数没有指明基类部分(基类子对象)的初始化方式,那么编译器将会自动调用基类的无参构造函数来初始化。
2)如果希望基类子对象以有参的方式被初始化,需要在子类构造函数的初始化表中指明其初始化方式:

class 子类:public 基类
{
   //基类(...):指明基类子对象的初始化方式
   子类(...):基类(...{}
}
  1 #include <iostream>
  2 using namespace std;
  3 
  4 class Base
  5 {
  6 public:
  7   Base(void):m_i(0)
  8   {
  9     cout << "Base::Base(void)" << endl;
 10   }
 11   Base(int i):m_i(i)
 12   {
 13     cout << "Base::Base(int)" << endl;
 14   }
 15   
 16   int m_i;
 17 };
 18 
 19 class Derived:public Base
 20 {
 21 public:
 22   Derived(void)
 23   {
 24     cout << "Derived::Derived(void)" << endl;
 25   }
 26   //Base(i):指明基类子对象初始化方式
 27   Derived(int i):Base(i)
 28   {
 29     cout << "Derived::Derived(int)" << endl;
 30   }
 31 };
 32 
 33 int main(void)
 34 { 
 35   
 36   Derived d;
 37   cout << d.m_i << endl;//0
 38   
 39   Derived d2(123);
 40   cout << d2.m_i << endl;//123
 41   return 0;
 42 }

3)子类对象的构造过程:

=》分配内存
=》构造基类子对象(按继承表顺序)
=》构造成员子对象(按声明的顺序)
=》执行子类的构造函数代码
1 #include <iostream>
  2 using namespace std;
  3 
  4 class Member
  5 {
  6 public:
  7   Member(void):m_i(0)
  8   {
  9     cout << "Member::Member(void)" << endl;
 10   }
 11   Member(int i):m_i(i)
 12   {
 13     cout << "Member::Member(int)" << endl;
 14   }
 15   int m_i;
 16 };
 17 
 18 class Base
 19 {
 20 public:
 21   Base(void):m_i(0)
 22   { 
 23     cout << "Base::Base(void)" << endl;
 24   }
 25   Base(int i):m_i(i)
 26   { 
 27     cout << "Base::Base(int)" << endl;
 28   }
 29   
 30   int m_i;
 31 };
 32 
 33 class Derived:public Base
 34 {
 35 public:
 36   Derived(void)
 37   { 
 38     cout << "Derived::Derived(void)" << endl;
 39   }
 40   //Base(i):指明基类子对象初始化方式
 41   //m_m(i):指明成员子对象初始化方式
 42   Derived(int i):Base(i),m_m(i)
 43   { 
 44     cout << "Derived::Derived(int)" << endl;
 45   }
 46   
 47   Member m_m;//成员子对象
 48 };
 49 
 50 int main(void)
 51 { 
 52   
 53   Derived d;
 54   cout << d.m_i <<","<< d.m_m.m_i<< endl;//0
 55   
 56   Derived d2(123);
 57   cout << d2.m_i << "," << d2.m_m.m_i << endl;//123
 58   return 0;
 59 }

6. 子类的析构函数
1)子类的析构函数,无论是自己定义的还是编译器缺省提供的,都会自动调用基类的析构函数,析构基类子对象。
2)子类对象的析构过程:

--》执行子类析构函数代码
--》析构成员子对象(按声明的逆序)
--》析构基类子对象(按继承表的逆序)
--》释放内存
 1 #include <iostream>
  2 using namespace std;
  3 
  4 class Member
  5 {
  6 public:
  7   Member(void):m_i(0)
  8   { 
  9     cout << "Member::Member(void)" << endl;
 10   }
 11   Member(int i):m_i(i)
 12   { 
 13     cout << "Member::Member(int)" << endl;
 14   }
 15   ~Member(void)
 16   { 
 17     cout << "Member::~Member(void)" << endl;
 18   }
 19   int m_i;
 20 };
 21 
 22 class Base
 23 {
 24 public:
 25   Base(void):m_i(0)
 26   { 
 27     cout << "Base::Base(void)" << endl;
 28   }
 29   Base(int i):m_i(i)
 30   { 
 31     cout << "Base::Base(int)" << endl;
 32   }
 33   ~Base(void)
 34   {
 35     cout << "Base::~Base(void)" << endl;
 36   }
 37   
 38   int m_i;
 39 };
 40 
 41 class Derived:public Base
 42 {
 43 public:
 44   Derived(void)
 45   { 
 46     cout << "Derived::Derived(void)" << endl;
 47   }
 48   //Base(i):指明基类子对象初始化方式
 49   //m_m(i):指明成员子对象初始化方式
 50   Derived(int i):Base(i),m_m(i)
 51   { 
 52     cout << "Derived::Derived(int)" << endl;
 53   }
 54   ~Derived(void)
 55   {
 56     cout << "Derived::~Derived(void)" << endl;
 57   }
 58   
 59   Member m_m;//成员子对象
 60 };
 61 
 62 int main(void)
 63 {
 64 
 65   Derived d;
 66   cout << d.m_i <<","<< d.m_m.m_i<< endl;//0
 67 
 68   //Derived d2(123);
 69   //cout << d2.m_i << "," << d2.m_m.m_i << endl;//123
 70   return 0;
 71 }

3)基类的析构函数不会自动调用子类的析构函数。如果对一个指针子类对象的激烈指针适用delete操作符,实际被执行的仅是基类的析构函数,子类的析构函数执行不到,有内存泄露的风险。

class A{...};
class B:public A{...}
A* pa = new B;//pa:指向子类对象的基类指针
delete pa;//内存泄露

7. 子类的拷贝构造和拷贝赋值
1)拷贝构造函数
1.1)子类没有定义拷贝构造函数,编译器会为子类提供缺省的拷贝构造函数,该函数会自动调用基类的拷贝构造函数,以拷贝的方式来初始化基类子对象。
1.2)子类定义了拷贝构造函数,那么需要 使用初始化表显示指明基类子对象也要以拷贝方式来初始化:

class Base{...};
class Derived
{
public:
	//Base(that):指明基类自队形以拷贝方式来初始化
	Devied(const Derived& that):Base(that),...{}
};

2)拷贝赋值操作符函数
2.1)子类没有定义拷贝赋值函数,编译器会为子类提供缺省的拷贝赋值函数,该函数会自动调用基类的拷贝赋值函数,完成对基类子对象的复制。
2.2)子类定义了拷贝赋值函数,需要显式调用基类的拷贝赋值函数,完成对基类子对象的复制。

class Base{...};
class Derived
{
   Derived& operator=(const Derived& that)
   {
   ......
   //显示调用基类的拷贝赋值函数
   Base::operator=(that);
   }
};
 1 #include <iostream>
  2 using namespace std;
  3 
  4 class Base
  5 {
  6 public:
  7   Base(void):m_i(0){}
  8   Base(int i):m_i(i){}
  9   Base(const Base& that):m_i(that.m_i)
 10   {
 11     cout << "Base::copy func" << endl;
 12   }
 13   Base& operator=(const Base& that)
 14   {
 15     cout << "Base::operat=" << endl;
 16     if(&that != this)
 17     { 
 18       m_i = that.m_i;
 19     }
 20     return *this;
 21   }
 22   int m_i;
 23 };
 24 
 25 class Derived:public Base
 26 {
 27 public:
 28   Derived(void):m_i(0){}
 29   Derived(int i1, int i2):Base(i1),m_i(i2){}
 30   
 31   //Base(that):指明基类子对象以拷贝方式初始化
 32   Derived(const Derived& that)
 33     :m_i(that.m_i), Base(that){}
 34   
 35   Derived& operator=(const Derived& that)
 36   {
 37     if(&that != this)
 38     {
 39       m_i = that.m_i;
 40       //Base::m_i = that.Base::m_i;
 41       //调用基类的拷贝赋值,复制基类子对象
 42       Base::operator=(that);
 43     }
 44     return *this;
 45   }
 46   
 47   int m_i;
 48 };
 49 
 49 
 50 
 51 int main(void)
 52 { 
 53   Derived d1(100, 200);
 54   Derived d2(d1);//等价于Derived d2 = d1; 
 55   cout << d1.Base::m_i << " , " << d1.m_i << endl;
 56   cout << d2.Base::m_i << " , " << d2.m_i << endl;
 57   
 58   Derived d3;
 59   d3 = d1;//d3.operator=(d1)
 60   cout << d3.Base::m_i << " , " << d3.m_i << endl;
 61 
 62   return 0;
 63 }

8. 多重继承
1)一个子类同时继承多个基类,这样的继承结果成为多重继承。
2)多重继承在向上造型的转换时,编译器会很具各个基类子对象的内存布局,进行适当的偏移计算,保证指针的类型与其所指向的目标对象一致。

1 #include <iostream>
  2 using namespace std;
  3 
  4 class Phone
  5 {
  6 public:
  7   Phone(const string& number):m_number(number){}
  8   
  9   void call(const string& number)
 10   { 
 11     cout << m_number << " call " << number << endl;
 12   }
 13 private: 
 14   string m_number;
 15 };
 16 
 17 class Player
 18 {
 19 public:
 20   Player(const string& media):m_media(media){}
 21 
 22   void play(const string &music)
 23   {
 24     cout << m_media << " play " << music << endl;
 25   } 
 26 private:
 27   string m_media;
 28 };
 29 
 30 class Computer
 31 {
 32 public:
 33   Computer(const string &os):m_os(os){}
 34   
 35   void run(const string &app)
 36   {
 37     cout << " on " << m_os << " run " << app << endl;
 38   }
 39   
 40 private:
 41   string m_os;
 42 };
 43 
 44 class SmartPhone:public Phone, public Player, public Computer
 45 { 
 46 public:
 47   SmartPhone(const string &number, const string &media, const string &os)
 48       :Phone(number), Player(media), Computer(os){}
 49 };
 50 
 51 int main(void)
 52 {
 53   SmartPhone iphoneX("1888001000", "MP4", "andriod");
 54   iphoneX.call("010-001");
 55   iphoneX.play("sun.mp3");
 56   iphoneX.run("LOL");
 57  
 58   SmartPhone *p1 = &iphoneX;
 59   //向上造型
 60   Phone *p2 = p1;
 61   Player * p3 = p1;
 62   Computer *p4 = p1;
 63 
 64   cout << "sizeof(string) : " << sizeof(string) << endl;
 65   cout << "p1 = " << p1 << endl;
 66   cout << "p2 = " << p2 << endl;
 67   cout << "p3 = " << p3 << endl;
 68   cout << "p4 = " << p4 << endl;
 69 
 70   return 0;
 71 }

3)名字冲突问题
一个子类的多个基类如果存在相同的成员,当通过子类访问这些成员时,编译器会报歧义错误—名字冲突。(作用域限定方法解决)
解决名字冲突的一般做法就是显示的使用作用域限定操作符,指明所访问的成员属于哪个基类;
如果产生冲突的成员是成员函数并且满足不同参数的条件,则还可以通过using声明,让它们在子类中形成重载关系,通过重载解析来解决。

eg:
class Base1
{
public:
	int m_i;
};
class Base2
{
public:
	int m_i;
};
class Derived:public Base1, public Base2
{
   //子类中访问m_i; error
};

9. 钻石继承
1)定义:一个子类的多个基类源自共同的基类祖先,这样的继承结构成为钻石继承。

   A(int m_i)
  /  \
  B  C
  \  /
   D
  1 #include <iostream>
  2 using namespace std;
  3 
  4 class A
  5 {
  6 public:
  7   A(int data):m_data(data){}
  8 protected:
  9   int m_data;
 10 };
 11 
 12 class B: virtual public A //虚继承
 13 {
 14 public:
 15   B(int data):A(data){}
 16   void set(int data)
 17   {
 18     m_data = data;
 19   }
 20 };
 21 
 22 class C: virtual public A //虚继承
 23 {
 24 public: 
 25   C(int data):A(data){}
 26   int get(void)
 27   { 
 28     return m_data;
 29   }
 30 };
 31 
 32 class D: public B, public C
 33 {
 34 public:
 35  //虚继承时,D类构造函数负责构造A基类子对象
 36   D(int data):B(data),C(data),A(data){}
 37 };
 38 
 39 int main(void)
 40 { 
 41   D d(100);
 42   cout << d.get() << endl;//100
 43   d.set(200);
 44   cout << d.get() << endl;//100,error
 45   
 46   return 0;
 47 }

2)公共基类(A)子对象在汇聚子对象(D)对象中,存在多个 实例,在汇聚子类中或者通过汇聚子类对象,去访问公共基类的成员,会因为继承路径不同而导致结果不一致。
3)通过虚继承可以让公共基类(A)子对象在汇聚子类(D)对象中实例唯一,并为所有中间(B,C)子类对象共享,这样即使通过不同的继承路径所访问到公共基类的成员一定是一致的。

   A (int m_i)(虚基类)
  /  \(虚继承)
  B  C  (virtual B, C)
  \  /
   D

10. 虚继承语法
1)继承表中使用virtual关键字
2)位于继承链最末端子类负责构造公共基类子对象。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验题目1:班级学生学期成绩管理系统 (1)程序功能简介 灵活运用继承、对象成员等机制,设计一个能够实现班级学生学期成绩管理的程序。 (2)程序设计说明 ① 个人信息CPerson的数据成员有姓名、性别、年龄、身份证号等数据成员,成员函数根据需要自行设计; ② 学生CStudent从CPerson派生,并增加学号、CCourse对象成员数组(大小至少3个)等数据成员,并根据需要自行设计成员函数,包括能够求解所选修课程的总学分、显示某个学生基本信息和课程信息的成员函数; ③ 课程CCourse包括课程名、学分、分数、任课老师等数据成员,成员函数根据需要自行设计; ④ 班级CClass的数据成员有班级名称、班级人数、CStudent对象成员数组(大小由构造函数确定)等。本班级CClass的对象成员数组需要在构造函数用new动态分配内存空间,在析构函数用delete释放。在CClass设计包括能够求解最高成绩、最低成绩和平均成绩以及通过学号查找并输出某个学生全部信息(例如Seek())等功能在内的成员函数; ⑤ 构造三十个学生的数据,每个学生都有三门课程成绩,输出并显示这些数据; ⑥ 根据的需要添加适当的其它成员,编写完整的程序并测试。 (3)程序调试运行 运行程序查看结果,并进行源代码调试和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值