继承和派生
面向对象的语言有三种特性封装,继承和多态。
C++的1可重用性
是通过继承这一机制来实现的。
继承的基本概念
继承是类之间定义的一种重要关系
一个B类继承A类,或称从A类派生B类
类A称为基类(父类),类B称为派生类(子类)
见如下代码:
class A
{
public:
func()
{
}
int a;
};
class B :public A //出现这样的形式就是类B继承于类A(类B包含于类A中所有的东西)
{
public:
funB()
{
cout << a << endl;
}
};
下面举个例子:
#include "stdafx.h"
#include <string>
using namespace std;
class Student
{
public:
Student(int id, string name)
{
this->id = id;
this->name = name;
}
void printS()
{
cout << "id = " << this->id << ", name = " << this->name << endl;
}
private:
int id;
string name;
};
//创建一个新的学生类,增加score、功能
class Student2 :public Student
{
public:
Student2(int id,string name,int score) :Student(id,name)//利用父类构造函数来给子类初始化
{
this->score = score;
}
void printS()
{
Student::printS();
cout << "score = " << this->score << endl;
}
private:
int score;
};
int main()
{
Student2 s2(1, "zhangsan", 80);
s2.printS();
return 0;
}
* 注意:
* 公有继承public(形式:class B :public A)
父类的public成员变量,在继承类的内部和外部都可以访问
父类的protected成员变量,在继承类的内部可以访问,在类的外部不可以访问。
父类的private成员变量,在继承类的内部和外部都不可以访问。
* 保护继承protected(形式:class B :protected B)
父类的public成员变量,在继承类的内部可以访问,外部不可以访问。但在继承类的公有继承子类中此成员变量可以被访问,所以父类中的public成员变量在变为protected变量。
父类的protected成员变量,在继承类的内部可以访问,在类的外部不可以访问。在继承类中为protected变量.
父类的private成员变量,在继承类的内部和外部都不可以访问。
类的赋值兼容原则
- 子类对象可以直接调用父类中的成员函数
- 子类对象可以直接赋值给父类对象。
- 子类对象可以直接初始化父类对象。
- 父类引用可以直接引用子类对象。
- 父类指针可以直接指向子类对象。
Parent *pp = NULL; //父类指针
Child *cp = NULL; //子类指针
parent p; //父类对象
Child c; //子类对象
pp = &c; //ok c的内存布局能够满足父类指针的全部需求,可以用一个儿子的对象地址给父类指针赋值
cp = &p; //error
子类的构造和析构
在调用子类的构造函数的时候,一定会调用父类的构造函数。父类先构造,子类后构造。
class Parent {
public:
Parent(int a)
{
this->a = a;
cout << "Parent(int)" << endl;
}
~Parent()
{
cout << "~Parent()" << endl;
}
protected:
int a;
};
class Child :public Parent
{
public:
Child(int a, int b) :Parent(a)
{
this->b = b;
cout << "Child(int a,int b)" << endl;
}
void PrintC()
{
cout << "a = " << a << ", b = " << b << endl;
}
~Child()
{
cout << "~Child()" << endl;
}
private:
int b;
};
int main()
{
Child c(10, 20);
c.PrintC();
return 0;
}
多继承和虚继承
多继承:
class Father
{
};
class Mother
{
};
class Child :public Father,public Mother
{
};
虚继承:
当有两个父类都继承同一个爷爷类时,那么子类在调用爷爷类的成员函数的时候就会出现拷贝多分成员变量,因而出现歧义,此时须将父类继承爷爷类改为虚继承。
class father :virtual public Grandfather
{
};
多态
如果有几个以上相似而不完全相同的对象,有时人们要求在向它们发出同一个消息时,它们的反应各不相同,分别执行不同的操作。这种现象就是多态现象。
C++中所谓的多态
是指,由继承而产生的相关的不同的类,其对象对同一消息会作出不同的响应。
方法:如果在父类和子类的成员函数中都有一个相同名字的成员函数,那么在外界函数调用子类或者父类时,要想传递进来的是子类,就调用子类的成员函数;若传递进来的是父类,就调用父类的成员函数,那么就得让父类的成员函数称为虚函数
。即在父类成员函数名的最前面加virtual关键字。
* 多态发生的三个必要条件:
1. 要有继承。
2. 要有虚函数重写。
3. 父类指针或引用 指向 子类对象。
虚析构函数
在多态时,要调用析构函数时,注意在父类的析构成员函数前加virtual。
virtual ~A()
{
cout << "~A()..." << endl;
if (this->p != NULL)
{
delete[] this->p;
this->p = NULL;
}
这样才能先析构子类再析构父类。
重载 重定义 重写
- 重载:一定发生在同一个作用域下。
- 重定义:是发生在两个不同的类中,一个是父类,一个是子类。
1. 普通函数重定义。 //如果父类的普通成员函数,被子类重写,说是重定义,
2.虚函数重写。 //如果父类的虚函数,被子类重写,就是虚函数重写。