【C++】六、继承与多态

文章目录

  • 1.继承
    • 1.1 定义
    • 1.2 基类派生类
    • 1.3 访问控制和继承的方式
    • 1.4 继承中构造与析构调用原则
    • 1.5 继承中同名成员变量处理
    • 1.6 派生类中的static关键字
      • 1.6.1 静态数据成员
      • 1.6.2 静态成员函数
      • 1.6.3 代码
    • 1.7 多继承带来的二义性
      • 1.7.1 什么是多重继承的二义性
      • 1.7.2 解决办法
  • 2.多态
    • 2.1 静态多态
    • 2.2 动态多态

1.继承

对于继承的基础知识点参考:c++继承,下面就不过多阐述。没有记录的必要性

1.1 定义

1.2 基类派生类

1.3 访问控制和继承的方式

1.4 继承中构造与析构调用原则

构造;先构造父类,再构造成员变量,最后构造自己
析构:先析构自己,再构造成员变量,最后析构父类

构造即生成,析构即释放,释放是按生成的相反顺序!

1.5 继承中同名成员变量处理

  1. 当子类成员变量与父类成员变量同名时
  2. 子类依然从父类继承同名成员
  3. 在子类中通过作用域分辨符::进行同名成员区分(在派生类中使用基类的同名成员,显式地使用类名限定符)
  4. 同名成员存储在内存中的不同位置
#include
using namespace std;
 
class A
{
public:
	A(int a = 0, int b = 0)
	{
		this->a = a;
		this->b = b;
		cout << "我是爸爸构造"<<  endl;
	}
	~A()
	{
		cout <<"我是爸爸析构" << endl;
	}
	void printfB1()
	{
		cout << "爸爸b=" << b << endl;
	}
	int get()
	{
		return b;
	}
public:
	int a;
	int b;
};
class B :public A
{
public:
	B(int b = 0, int c = 0) 
	{
		this->b = b;
		this->c = c;
		cout << "我是儿子构造"<<  endl;
	}
	~B()
	{
		cout << "我是儿子析构"<< endl;
	}
	void printfB2()
	{
		cout <<"儿子b="<< b<< endl;
	}
	int get()
	{
		return b;
	}
public:
	int b;
	int c;
};
 
int main()
{
	//同名的成员变量相互独立,而同名的成员函数会发生覆盖。
	B b1;
	A a1;
	cout << "=====" << endl;
	//同名成员变量 
	b1.b = 11;
	b1.B::b = 12;
	b1.A::b = 22;
	b1.printfB1();
	b1.printfB2();
 	cout << "=====" << endl;
	//同名成员函数
	cout << b1.get()<< endl;//b1.B::get()
	cout << b1.B::get()<< endl;
	cout << b1.A::get()<< endl;
	cout << "=====" << endl;
	
}

1.6 派生类中的static关键字

1.6.1 静态数据成员

  • 基类定义的静态成员, 将被所有的派生类共享。
  • 静态数据成员在程序中只有一份拷贝, 由该类型的所有对象共享访问。
  • 静态数据成员和普通数据成员一样遵从访问控制原则。

1.6.2 静态成员函数

  • 出现在类体外的函数定义不能指定关键字static 。
  • 静态成员函数只能访问静态数据成员和静态成员函数。
  • 静态成员函数也遵从访问控制原则。

1.6.3 代码

#include

using namespace std;

class Base
{
public:
    //定义一个静态成员
    static int i;
    void print()
    {
        cout << "i: " << i << endl;
    }
    //静态成员函数只能在类的内部定义
    //只能使用静态成员函数和静态数据成员
    static void Add1()
    {
        i++;
    }
};
//对静态成员显式地进行初始化,让编译器分配内存空间
int Base::i = 0;

class Derived : public Base
{
public:
    void print()
    {
        cout << "i: " << i << endl;
    }
    static void Add2()
    {
        i += 2;
    }
};

int main()
{
    //在使用时,所有的基类和派生类对象使用的是同一个静态成员
    Base b1;
    b1.i = 2;
    b1.print();

    Derived d1;
    d1.print();
    d1.i = 5;
    d1.print();
    b1.print();

    b1.Add1();
    b1.print();

    d1.Add2();
    b1.print();
    d1.print();
    return 0;
}


1.7 多继承带来的二义性

参考 C++多继承中二义性的解决方案

1.7.1 什么是多重继承的二义性

如果一个派生类从多个基类派生,而这些基类又有一个共同的基类,则在对该基类中声明的成员变量进行访问时,可能产生二义性
【C++】六、继承与多态_第1张图片

1.7.2 解决办法

 
#include 
using namespace std;
 
class A{
public:
	int a;
	void f(){
		cout << "A.f() " << endl;
	};
};
 
class B1 : public A{
//class B1 : virtual public A{//【解决办法1】虚继承
public:
	int b1;
};
 
class B2 : public A{
//class B2 : virtual  public A{
public:
	int b2;
};
 
class C : public B1, public B2{
public:
	int c1;
	void f(){//【解决办法3】同名覆盖
		B1::f();
        cout << "C.f() " << endl;
    }
};
 
int main(){
	C  c1;
	c1.b1 = 100;
	c1.b2 = 200;
	c1.c1 = 300;
 
 //【解决办法1】虚继承
//	c1.a = 500; //继承的二义性 和 虚继承解决方案
 	
// 	【解决办法2】类名限定
	cout << c1.B1::a << endl;
	cout << c1.B2::a << endl;
// 【解决办法3】同名覆盖
	c1.f();

	return 0;
}

2.多态

【C++】六、继承与多态_第2张图片

2.1 静态多态

静态多态是编译器在编译期间完成的,编译器根据函数实参的类型(可能会进行隐式类型的转换),可推断出要调用哪个函数,如果有对应的函数就调用该函数,否则出现编译错误

2.2 动态多态

动态多态的实现条件

  • 继承
  • 基类中必须包含虚函数,并且派生类一定要对基类中的虚函数进行重写
  • 通过基类对象的指针或引用调用虚函数
#define _CRT_SECURE_NO_WARNING 1
 
#include 
#include 
#include 
#include 
#include 
using namespace std;
 
class FittingRoom
{
public:
	void GoToManFittingRoom()
	{
		cout<<"Man--->Please go to left"<<endl;
	}
	void GoToWomanFittingRoom()
	{
		cout<<"Woman--->Please go to right"<<endl;
	}
};
 
class Person
{
public:
	virtual void GotoFitttingRoom(FittingRoom& ft) = 0;
};
 
class Man:public Person
{
public:
	virtual void  GotoFitttingRoom(FittingRoom& ft)
	{
		ft.GoToManFittingRoom();
	}
};
 
class Woman:public Person
{
public:
	virtual void  GotoFitttingRoom(FittingRoom& ft)
	{
		ft.GoToWomanFittingRoom();
	}
};
 
void TestFittingRoom()
{
	FittingRoom ft;
	Person* p = NULL;
	for(int i = 1; i <= 10; ++i)
	{
		if( (rand()%i) & 0x01)
			p = new Man;
		else
			p = new Woman;
		p->GotoFitttingRoom(ft);
		delete p;
		Sleep(1000);
	}
}
 
int main()
{
	TestFittingRoom();
	return 0;
}

你可能感兴趣的:(C/C++)