NDK13_C++基础:继承与多态

NDK开发汇总

一 继承

继承

class A:[private/protected/public] B

默认为private继承

A是基类,B称为子类或者派生类

方式 说明
public 基类的public、protected成员也是派生类相应的成员,基类的private成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
protected 基类的公有和保护成员将成为派生类的保护成员
private 基类的公有和保护成员将成为派生类的私有成员
class Parent {
public:
	void test() {
		cout << "parent" << endl;
	}
};

class Child :   Parent {
public:
	void test() {
         // 调用父类 方法
		Parent::test();
		cout << "child" << endl;
	}
};

多继承

一个子类可以有多个父类,它继承了多个父类的特性。

class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…

1 一个最简单的继承案例

  1. 构造函数与析构函数的调用顺序 子类对象调用父类的成员
    定义父类:
    plane.h
#pragma once
#include
class Plane
{
public:
	Plane();
	Plane(std::string name,int year);
	~Plane();

	void fly();

	void land();

	void printf();

protected:
	std::string name;
	int year;
};

plane.cpp

#include 
#include 


using namespace std;

Plane::Plane() :name("湾流"), year(1991)
{
	cout << "Plane 无参构造函数" << this << name << year << endl;
}

Plane::Plane(std::string name, int year):name(name),year(year)
{
	cout << "Plane 构造函数" << this <<name<<year<< endl;

}

Plane::~Plane()
{
	cout << "Plane 析构函数" << this << name << year << endl;
}


void Plane::fly() {
	cout << "Plane fly"  << endl;
}

void Plane::land() {
	cout << "Plane land" << endl;
}

void Plane::printf() {
	cout << "Plane printf" << "name = "<< name<<"year = " << year << endl;
}

子类继承
Jet.h

#pragma once
#include
class Jet:public Plane
{
public:
	Jet();
	Jet(std::string name, int year);
	~Jet();

private:
};

Jet.cpp

#include 
#include 


using namespace std;

Jet::Jet() {

	cout << "Jet  无参构造函数" << name << year << endl;
}

Jet::Jet(std::string name, int year) {

	cout << "Jet  构造函数" << name << year << endl;
}


Jet::~Jet() {
	cout << "Jet 析构函数" << endl;
}

调用:

#include 
#include 
#include 



using namespace std;

void func() {
	Jet jet;	
	jet.fly();
}

void main() {
	func();
	system("pause");
}

打印结果:

Plane 无参构造函数010FFB40湾流1991
Jet  无参构造函数湾流1991
Plane fly
Jet 析构函数
Plane 析构函数010FFB40湾流1991

如果Jet中重写fly方法,则调用Jet的fly方法;子类没有,就使用父类的,子类有实现,就用子类。

如果想子类调用父类的方法:
jet.Plane::fly();

重载(overload): 在相同作用域内,函数名称相同,参数或常量性(const)不同的相关函数称为重载。重载函数之间的区分主要在参数和常量性(const)的不同上,若仅仅是返回值或修饰符 virtual,public/protected/private的不同不被视为重载函数(无法通过编译)。不同参数是指参数的个数或类型不同,而类型不同是指各类型之间不能进行隐身类型转换或不多于一次的用户自定义类型转换(关于类型转换,请参考前文:类型转型(Type Casting))。当调用发生时,编译器在进行重载决议时根据调用所提供的参数来选择最佳匹配的函数。

重写(override):派生类重写基类中同名同参数同返回值的函数(通常是虚函数,这是推荐的做法)。同样重写的函数可以有不同的修饰符virtual,public/protected/private。

  1. 父类型引用 赋值子类型的对象,调用的是父类型中的方法
void func() {
	Jet jet;	
	Plane *p1 = &jet;
	p1->fly();

	Plane &p2 = jet;
	p2.fly();
}

运行结果

Plane 无参构造函数00AFFB60湾流1991
Jet  无参构造函数湾流1991
Plane fly
Plane fly
Jet 析构函数
Plane 析构函数00AFFB60湾流1991
  1. 给父构造函数传参,同时给对象赋值

    **重载(overload):**在相同作用域内,函数名称相同,参数或常量性(const)不同的相关函数称为重载。重载函数之间的区分主要在参数和常量性(const)的不同上,若仅仅是返回值或修饰符 virtual,public/protected/private的不同不被视为重载函数(无法通过编译)。不同参数是指参数的个数或类型不同,而类型不同是指各类型之间不能进行隐身类型转换或不多于一次的用户自定义类型转换(关于类型转换,请参考前文:类型转型(Type Casting))。当调用发生时,编译器在进行重载决议时根据调用所提供的参数来选择最佳匹配的函数。

重写(override):派生类重写基类中同名同参数同返回值的函数(通常是虚函数,这是推荐的做法)。同样重写的函数可以有不同的修饰符virtual,public/protected/private。

2.继承的权限

基类中 继承方式 子类中
public & public继承 => public
public & protected继承 => protected
public & private继承 => private

protected & public继承 => protected
protected & protected继承 => protected
protected & private继承 => private

private & public继承 => 子类无权访问
private & protected继承 => 子类无权访问
private & private继承 => 子类无权访问

3.继承的二义性 多继承 虚继承

解决二义性 虚进程 ----> 不同路径继承来的同名成员 只有一份拷贝,解决不明确的问题

class A
{
public:
	string name;
};

class A1: public A
{	 
};

class A2 :  public A
{
};



class B : public A1, public A2
{


};

B b;
//只能显示调用
b.A1::name = “Tim”;
b.A2::name = “AV”;
b.A::name = “ricky”;
如果想直接使用b.name ,需要虚继承

class A1 :virtual public A
{
};

class A2 : virtual public A
{
};

二 多态

多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。

  • 静态多态(静态联编) 是指在编译期间就可以确定函数的调用地址,通过函数重载模版(泛型编程) 实现

// 重载(函数名称相同,参数不同,面向对象的特效,c 中不行)

  • 动态多态(动态联编) 是指函数调用的地址不能在编译器期间确定,必须需要在运行时才确定 ,通过继承+虚函数 实现

//程序运行过程中,觉得哪一个函数被调用

发生多态的条件:

  1. 继承
  2. 父类的引用或者指针指向子类的对象
  3. 函数的重写

三 Demo

Extension.zip

你可能感兴趣的:(NDK)