继承与多态小结
继承
C++的继承和java的类似,都是派生类继承基类的对象和函数,不同点是C++支持多继承,而java只支持单继承
C++多继承实例
#include <iostream>
using namespace std;
class Father
{
public:
Father()
{
cout<<"Father\n";
}
};
class Mother
{
public:
Mother()
{
cout<<"Mother\n";
}
};
class Child : public Father, public Mother
{
//之后称为类派生表,表的顺序决定基类构造函数调用的顺序,析构函数的调用顺序正好相反
};
int main()
{
Child child;
return 0;
}
继承方式的分类
有三种继承方式,分别是公有继承,保护继承和私有继承。
区别
基类的公有成员,子类可以继承为自己的公有成员。在派生类可以访问,在外部也可以访问。
基类的私有成员,子类不可以访问。
基类的保护成员,子类可以继承为自己的保护成员,在派生类可以访问,在外部不可以访问。
公有继承
示例
#include<iostream>
#include<string>
using namespace std;
class Student
{
public :
Student(string s, int g,int a)
{
cout << "Constuct Student" << endl;
name = s;
grade = g;
age = a;
}
void print()
{
cout << "Student:" << endl;
cout << "name=" << name << endl;
cout << "grade=" << grade<<endl;
cout << "age=" << age << endl;
}
protected:
string name;
int grade;
private:
int age;
};
class GraduateStudent :public Student //继承方式i
{
public:
GraduateStudent(string s, int g, int a) :Student(s, g, a) //调用基类的构造函数,构造基类
{
cout << "Constuct GraduateStudent" << endl;
}
/*
公有继承方式,会把基类的公有成员(变量和函数)继承到子类公有成员,保护成员
变成基类的保护成员,但是私有成员子类也一样不可以访问
*/
void print1()
{
cout << "GraduateStudent:" << endl;
cout << "name= " << name << endl;
cout << "grade= " << grade << endl;
}
};
void main()
{
GraduateStudent g("Ouyang", 95, 21);
g.print(); //子类可以直接访问基类公共成员成员
g.print1();
system("pause");
}
保护继承
#include<iostream>
#include<string>
using namespace std;
class Student
{
public :
Student(string s, int g,int a)
{
cout << "Constuct Student" << endl;
name = s;
grade = g;
age = a;
}
void print()
{
cout << "Student:" << endl;
cout << "name=" << name << endl;
cout << "grade=" << grade<<endl;
cout << "age=" << age << endl;
}
string name; //公有成员
int grade;
private:
int age;
};
class GraduateStudent :protected Student //继承方式i
{
public:
GraduateStudent(string s, int g, int a) :Student(s, g, a) //调用基类的构造函数,构造基类
{
cout << "Constuct GraduateStudent" << endl;
}
/*
保护继承方式,会把基类的公有成员或者保护成员(变量和函数)变成子类的保护成员,但是私有成员子类也一样不可以访问
*/
void print1()
{
cout << "GraduateStudent:" << endl;
cout << "name= " << name << endl;
cout << "grade= " << grade << endl;
}
};
void main()
{
GraduateStudent g("Ouyang", 95, 21);
//g.print(); 编译出错 无法直接访问子类的公有成员了
g.print1();
system("pause");
}
私有继承
基类的对象在派生类中不可见,但是派生类可以重写覆盖
#include <iostream>
using namespace std;
class A
{
private:
int a;
protected:
int b;
public:
int c;
void show()
{
cout << "a = " << a << "b = " << b << "c = " << c <<endl;
}
int set(int a,int b,int c)
{
this->a = a;
this->b = b;
this->c = c;
}
int get_a()
{
return a;
}
int get_b()
{
return b;
}
};
class B : private A
{
private:
int x;
protected:
int y;
public:
int z;
void show()
{
cout << "a = " << get_a() << "," << "b = " << b << "," << "c = " << c << "," << "x = " << x << "," << "y = " << y << "," << "z = " << z <<endl;
}
int set(int a,int b,int c,int x,int y,int z)
{
A::set(a,b,c);
this->x = x;
this->y = y;
this->z = z;
}
int get_a()
{
return A::get_a();
}
int get_b()
{
return b;
}
int get_c()
{
return c;
}
int get_x()
{
return x;
}
int get_y()
{
return y;
}
};
int main()
{
B b;
b.set(10,20,30,40,50,60);
b.show();
cout << "a = " << b.get_a() <<endl;
cout << "b = " << b.get_b() <<endl;
cout << "c = " << b.get_c() <<endl;
cout << "x = " << b.get_x() <<endl;
cout << "y = " << b.get_y() <<endl;
cout << "z = " << b.z <<endl;
return 0;
}
多态
在不同类型的对象调用相同的函数所产生的不同的结果我们称之为多态。
具体的说,它主要表现在函数调用时,实现一种接口,多种方法,多态性是面向对象程序设计的另一个重要特征。C++支持两种多态性,编译时多态性和运行时的多态性。
编译时的多态性:属于某个类的不同对象,或不同环境下的同一对象,调用了名称相同的成员函数,所完成的功能却不相同,这是一种静态多态性,因为编译器在对源程序进行编译时,即可确定所要调用的是哪个函数或者,通过重载机制即可实现。
运行时多态性:属于某个基类的不同派生对象,在形式上调用的是继承自己基类的同一成员函数。实际上调用的却是各自派生的同名成员函数,这是一种动态多态性,因为函数名,函数参数和返回类型,都相同的情况下,编译阶段不能确定要调用的函数,只能在程序运行时确定这种多态性,这种多态性通过虚函数机制来实现。
多态的实现方式
依赖于虚函数实现,之所以虚函数可以分清楚当前调用的函数是基类的还是派生类的,主要在于基类和派生类分别有着自己的虚函数表,再调用虚函数时,它们是通过去虚函数表去对应的函数的。
示例
#include<iostream>
using namespace std;
class A
{
public :
void print()
{
cout << "A" << endl;
}
virtual void print1()
{
cout << "Virtual A" << endl;
}
};
class B:public A{
public:
void print() { cout << "B" << endl; }
virtual void print1() { cout << "Virtual B" << endl; }
};
void fn(A & s)
{
s.print();
s.print1();
}
int main()
{
A a;
B b;
fn(a);
fn(b);
return 0;
}
公共派生类对象取代这种取代有以下三种情况:
1.派生类对象给基类对象赋值
2.派生类对象初始化基类对象的引用
3.使基类的指针指向派生类对象(实现虚函数的关键)
示例
class Base
{
public:
void funpublic()
{
cout<<"基类的成员函数"<<endl;
}
};
class child1:public Base
{
public:
void funpublic()
{
cout<<"派生类child1的成员函数"<<endl;
}
};
class child2:public Base
{
public:
void funpublic()
{
cout <<"派生类child2的成员函数"<<endl;
}
};
int main() {
Base * p1,*p2,*p3,base;
child1 obj1;
child2 obj2;
base =obj1;
base.funpublic();
Base &aliasbase=obj2;
aliasbase.funpublic();
p1=&obj1;
p2=&obj2;
p1->funpublic();
p2->funpublic();
p2=new child1;
p2->funpublic();
p3=new child2;
p3->funpublic();
return 0;
}