Chinaunix首页 | 论坛 | 博客
  • 博客访问: 65247
  • 博文数量: 50
  • 博客积分: 2360
  • 博客等级: 大尉
  • 技术积分: 620
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-02 15:59
文章分类

全部博文(50)

文章存档

2011年(1)

2009年(49)

我的朋友

分类: C/C++

2009-09-06 14:52:47

继承与派生初步

一、什么是继承与派生?

新类从已有类那里得到已有的成员(数据成员和成员函数)。新类称为派生类或子类,已有类称为基类或父类。也可以说,已有类产生新类的过程就是类的派生。

注意:

1、  类的继承和派生是面向对象的最重要特征之一;

2、  类的继承与派生大大提高了C++的代码重用率;

3、  派生类可以作为基类继续派生出多个新类;

4、  一个基类可以派生多个派生类,一个派生类也可以从多个基类继承而来(多继承)。

5、  构造函数和析构函数不能被继承(派生);

6、  类的继承方式有三种:publicprivateprotected

二、类的三种继承方式(基类的成员在派生类中的等价权限)

       public继承:

基类(父类)

派生类(子类)

public

public

protected

protected

private

×

特点:派生类拥有了基类的共有成员和保护成员,是最常用的继承方式。

private继承:

基类(父类)

派生类(子类)

public

private

protected

private

private

×

特点:把基类中的成员私有化。

protected继承:

基类(父类)

派生类(子类)

public

protected

protected

protected

private

×

       注意:在继承关系中,基类的private成员不但不能被类外访问(对应用程序隐藏),而且对派生类也是隐藏,而基类的protected成员不能被类外访问,但对派生类来说是不隐藏的。

三、派生类的构造函数和析构函数

       基类中两类特殊函数不能被继承——构造函数和析构函数。

生成对象时,先调用基类的默认构造函数,再调用派生类的默认构造函数;撤销对象时,先调用派生类的默认析构函数,再调用基类的默认析构函数。

class Person

{

private:

       char name[10];

public:

       Person(){};

};

class Student:public Person

{

private:

       int grade;

public:

       Student(){};

};

void main()

{

       Student s;//生成对象时,先调用Person的默认构造函数,再调用Student的默认构造函数

}//撤销对象时,先调用Student的默认析构函数,再调用Person的默认析构函数

当我们想在初始化s的时候,获得一个姓名和年级,该怎么办呢?年级我们完全可以通过重载Student来初始化,至于姓名,我们可以重载一个Person的构造函数。通过向基类构造函数传递参数实现基类的初始化。如下:

Person(char *n)

{strcpy(name,n);}

Student(int g, char *n):Person(n)//向基类构造函数传递参数

{grade = g;}

完整的调试程序如下:

#include

#include

class Person

{

private:

       char name[10];

public:

       Person(char *n){strcpy(name,n);}

       Person(){};

       void displayName(){cout<同学:";};

};

class Student:public Person

{

private:

       int grade;

public:

       Student(){};

       Student(int g, char *n):Person(n)

       {grade = g;}

       void displayGrade(){cout<年级"<

};

void main()

{

       Student s(2,"张飞");

       s.displayName();

       s.displayGrade();

}

派生类含有对象成员的情况,可以把对象成员看成一个普通的变量类型。如下程序:


#include

#include

class Cource

{

private:

       char name[20];

       int mark;

public:

       Cource(char *n, int m)

       {strcpy(name,n);mark = m;}

       void displayMark(){cout<";}

};

 

class Person

{

private:

       char name[10];

public:

       Person(char *n){strcpy(name,n);}

       Person(){}

       void SetName(char *n){strcpy(name,n);}

       void displayName(){cout<同学:";}

};

class Student:public Person

{

private:

       int grade;

       Cource c;

public:

       void displayGrade(){cout<年级";c.displayMark();}

       Student(int g,char *n1,char *n2,int m):Person(n1),c(n2,m)

       {grade = g;}

       void SetGrade(int g){grade = g;}

};

void main()

{

       Student s(2,"张飞","面向对象程序设计",98);

       s.displayName();

       s.displayGrade();

}


 

为了更好的理解我们可以把:

       Student(int g,char *n1,char *n2,int m):Person(n1),c(n2,m)

       {grade = g;}

等价写成:    Student(int g,char *n1,char *n2,int m):Person(n1),c(n2,m),grade(3){}

一般会重载没有参数的构造函数,便于建立没有初值的对象,更完整的程序见附录!

四、多继承

       多继承和单继承的区别在于它们基类的个数。

例:

class Teacher

{};

class Student

{};

class Teach_Assistant:public Teacher,public Student

{

}

       如果Teacher Student基类相同,可能会产生二义性问题!如:


#include

#include

class Person

{

private:

       char name[10];

public:

       Person(char *n){strcpy(name,n);}

       Person(){}

       void displayName(){cout<<"输出名字!";}

};

class Student:public Person

{};

class Teacher:public Person

{};

class Teach_Assistant:public Teacher,public Student

{

//public:

//     void displayName();

};

//void Teach_Assistant::displayName()

//{

//     Teacher::displayName();

//}

void main()

{

       Teach_Assistant ta;

       ta.displayName();

}


当如上注释掉几条语句后,编译无法通过!

五、虚基类

       解决二义性问题!如下:


#include

#include

class Person

{

private:

       char name[10];

public:

       Person(char *n){strcpy(name,n);}

       Person(){}

       void displayName(){cout<<"输出名字!";}

};

class Student:virtual public Person

{};

class Teacher:virtual public Person

{};

class Teach_Assistant:public Teacher,public Student

{};

void main()

{

       Teach_Assistant ta;

       ta.displayName();

}


-----------------------------------------------------------------------

附录:


#include

#include

class Cource

{

private:

       char name[20];

       int mark;

public:

       Cource(){}

       Cource(char *n, int m)

       {strcpy(name,n);mark = m;}

       void displayMark(){cout<";};

       void Set(char *n,int m){strcpy(name,n);mark = m;};

};

 

class Person

{

private:

       char name[10];

public:

       Person(char *n){strcpy(name,n);}

       Person(){}

       void SetName(char *n){strcpy(name,n);}

       void displayName(){cout<同学:";}

};

class Student:public Person

{

private:

       int grade;

       Cource c;

public:

       void displayGrade(){cout<年级";c.displayMark();}

       Student(){}

       Student(int g,char *n1,char *n2,int m):Person(n1),c(n2,m)

       {grade = g;}

       void SetStu(int g,char *n1,char *n2,int m)

       {

              grade = g;

              SetName(n1);

              c.Set(n2,m);

       }

       void SetGrade(int g){grade = g;}

};

void main()

{

       Student s(2,"张飞"," 面向对象程序设计 ",98);

       s.displayName();

       s.displayGrade();

       cout<

       Student ss;

       ss.SetStu(2,"刘备"," 面向对象程序设计 ",93);

       ss.displayName();

       ss.displayGrade();

       cout<

}

阅读(413) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~