精华内容
下载资源
问答
  • C++ 多态

    2019-09-24 06:57:41
    C++ 多态多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。 1 #include <...

    C++ 多态
    多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。

    C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。

     

     1 #include <iostream>
     2 
     3 /* run this program using the console pauser or add your own getch, system("pause") or input loop */
     4 using namespace std;
     5 int fac(int);
     6 int main(int argc, char** argv) {
     7     int i;
     8     for(i=1;i<=5;i++)
     9     cout <<i<<"!="<<fac(i)<<endl;
    10     return 0;
    11 }
    12 
    13 int fac(int n)
    14 {
    15     static int f=1;
    16     f=f*n;
    17     return f;
    18 }

     

    转载于:https://www.cnblogs.com/borter/p/9401214.html

    展开全文
  • C++多态

    2019-04-12 20:03:04
    C++多态 多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。 C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。 静态链接(静态多态) ...

    C++多态

    多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。
    C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数

    静态链接(静态多态)

    函数调用在程序执行前就准备好了。有时候这也被称为早绑定。

    #include <iostream> 
    using namespace std;
     
    class Shape {
       protected:
          int width, height;
       public:
          Shape( int a=0, int b=0)
          {
             width = a;
             height = b;
          }
          int area()
          {
             cout << "Parent class area :" <<endl;
             return 0;
          }
    };
    class Rectangle: public Shape{
       public:
          Rectangle( int a=0, int b=0):Shape(a, b) { }
          int area ()
          { 
             cout << "Rectangle class area :" <<endl;
             return (width * height); 
          }
    };
    class Triangle: public Shape{
       public:
          Triangle( int a=0, int b=0):Shape(a, b) { }
          int area ()
          { 
             cout << "Triangle class area :" <<endl;
             return (width * height / 2); 
          }
    };
    // 程序的主函数
    int main( )
    {
       Shape *shape;
       Rectangle rec(10,7);
       Triangle  tri(10,5);
     
       // 存储矩形的地址
       shape = &rec;
       // 调用矩形的求面积函数 area
       shape->area();
     
       // 存储三角形的地址
       shape = &tri;
       // 调用三角形的求面积函数 area
       shape->area();
       
       return 0;
    }
    

    输出为:

    Parent class area
    Parent class area
    

    这里的原因就在于int area() 在父类这里没有使用关键字virtual来进行修饰。如果使用了该修饰符修饰,就会再次输出为:

    Rectangle class area
    Triangle class area
    

    编译器看的是指针的内容,而不是它的类型。因此,由于 tri 和 rec 类的对象的地址存储在 *shape 中,所以会调用各自的 area() 函数。
    正如您所看到的,每个子类都有一个函数 area() 的独立实现。这就是多态的一般使用方式。有了多态,您可以有多个不同的类,都带有同一个名称但具有不同实现的函数,函数的参数甚至可以是相同的。

    虚函数

    虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数
    我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。

    纯虚函数

    class Shape {
       protected:
          int width, height;
       public:
          Shape( int a=0, int b=0)
          {
             width = a;
             height = b;
          }
          // pure virtual function
          virtual int area() = 0; //这里就是纯虚函数,没有函数实现主体,这里的=0 是告诉编译器这里是纯虚函数。
    };
    
    展开全文
  • c++ 多态

    2021-03-23 20:40:33
    c++ 多态 多态表现为一个函数在不同情况下可以变现出不同的形式。 如: class Person { public void f() { print(i am person);} } class Male : Person { public void f() { print(i am male);} } class Female :...

    c++ 多态

    多态表现为一个函数在不同情况下可以变现出不同的形式。

    如:

    class Person {
    	public void f() { print(i am person);}
    }
    class Male : Person {
    	public void f() { print(i am male);}
    }
    class Female : Person {
    	public void f() { print(i am female);}
    }
    
    
    male.f(); //结果就是 "i am male"
    female.f(); //结果就是"i am female"
    

    同一个函数在不同的类中显示出了不同的情况,这就是多态,具体来说是静态多态。这里的函数f是被override(重写)了。

    对于多态还有动态多态,这种多态是知道程序被运行时才知道这个类调用的是什么函数。

    class Person {// 抽象类
    	public virtual void f() = 0;	//纯虚函数
    }
    class Male : Person {
    	public void f() { print(i am male);}
    }
    class Female : Person {
    	public void f() { print(i am female);}
    }
    
    
    
    Male * male = new Male;
    Person * person = male;
    person.f()
    

    输出结果为i am male,此时对于c++来说Person必须为抽象类。这就体现了动态多态。

    展开全文
  • c++多态

    2020-07-30 12:25:03
    C++多态总结(动态)多态概念(动态)多态底层(动态)多态优点纯虚函数和抽象类虚析构和纯虚析构 多态是C++面向对象三大特性封装、继承、多态之一 多态分为两类 静态多态: 函数重载 和 运算符重载属于静态多态,...

    多态是C++面向对象三大特性封装、继承、多态之一

    多态分为两类

    • 静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名。(和下面多态需要重写父类函数不同)
    • 动态多态: 派生类和虚函数实现运行时多态(父类对应属性,子类同样也对应有属性,需要用到多态情况下,在父类属性添加virtual修饰,子类可加可不加。)

    静态多态和动态多态区别:

    • 静态多态的函数地址早绑定 - 编译阶段确定函数地址
    • 动态多态的函数地址晚绑定 - 运行阶段确定函数地址

    (动态)多态概念

    父类动物在叫的函数;子类小狗在叫的函数,子类小猫在叫的函数。
    //我们希望传入什么对象,那么就调用什么对象的函数

    多态满足条件

    • 继承关系
    • 子类重写父类中的虚函数不是重载

    多态使用条件

    • 父类指针或引用指向子类对象

    重写:函数返回值类型 函数名 参数列表 完全一致称为重写

    class Animal
    {
    public:
    	//Speak函数就是虚函数
    	//函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。
    	virtual void speak()
    	{
    		cout << "动物在说话" << endl;
    	}
    };
    
    class Cat :public Animal 
    {
    public:
    	virtual void speak() //子类重写父类函数
    	{
    		cout << "小猫在说话" << endl;
    	}
    };
    
    class Dog :public Animal
    {
    public:
    
    	virtual void speak()  //子类重写父类函数
    	{
    		cout << "小狗在说话" << endl;
    	}
    
    };
    //我们希望传入什么对象,那么就调用什么对象的函数
    //如果函数地址在编译阶段就能确定,那么静态联编
    //如果函数地址在运行阶段才能确定,就是动态联编
    
    void DoSpeak(Animal & animal)
    {
    	animal.speak();
    }
    //
    //多态满足条件: 
    //1、有继承关系
    //2、子类重写父类中的虚函数
    //多态使用:
    //父类指针或引用指向子类对象
    
    void test01()
    {
    	Cat cat;
    	DoSpeak(cat);
    
    
    	Dog dog;
    	DoSpeak(dog);
    }
    
    
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    

    (动态)多态底层

    上述代码的Animal类的内存占4字节, 而去掉virtual变成1字节。则有virtual说明变成了vfptr(virtual function pointer 虚函数(表)指针),指向vftable(virtual function table虚函数表(里面存放了父类函数的入口地址))。

    1、如果没有父类指针或引用指向子类对象**,则没有多态产生。cat类vfptr指向vftable会继承存放父类的函数表一个函数的入口地址。
    2、当父类指针或引用指向子类对象**,cat类的vfptr指向vftable会存放自己virtual的对应重写的函数入口地址,替换掉1所说的函数入口地址。(子类函数重写加入virtual会比较好理解)

    (动态)多态优点

    步骤:
    1、通过给一个父类,里面的虚函数(virtual修饰)(下面会讲纯虚函数,此时父类仅仅只是一个抽象类,需要子类去重写纯虚函数实现功能。)没有写任何东西,在里面空着。
    2、
    (1)写一个要实现功能的子类,通过使用继承父类(抽象类)。.
    (2)父类引用、指针指向子类的对象。(1、可父类指针指向到new 子类在堆区开辟空间 ,记得内存释放 delete掉)(2、也可以使用引用指向一个子类对象,要创建子类对象,不用new且不用delete)
    (3)子类虚重写对应父类的虚函数。
    (4)利用多态来实现子类的函数,进行对整个程序架构的扩展(也可有利于多人协助,维护,可读性高,结构清晰)。

    • 代码组织结构清晰
    • 可读性强
    • 利于前期和后期的扩展以及维护
    • 总结:C++开发提倡利用多态设计程序架构,因为多态优点很多

    纯虚函数和抽象类

    在多态中,通常父类中虚函数的实现是毫无意义的,主要都是子类重写的该虚函数内容。

    因此可以将虚函数改为纯虚函数

    纯虚函数语法:virtual 返回值类型 函数名 (参数列表)= 0 ;

    当类中有了纯虚函数,这个类也称为抽象类

    抽象类特点

    • 无法实例化对象
    • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类

    虚析构和纯虚析构

    多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码。(因为子类在堆区开辟了空间,而父类只能delete父类自己的空间,而无法进入到子类去析构delete子类的空间

    解决方式:将父类中的析构函数改为虚析构或者纯虚析构

    虚析构和纯虚析构共性:

    • 可以解决父类指针释放子类对象
    • 都需要有具体的函数实现

    虚析构和纯虚析构区别:

    • 如果是纯虚析构,该类属于抽象类,无法实例化对象

    1、虚析构语法:

    virtual ~类名(){}

    2、纯虚析构语法:

    virtual ~类名() = 0;

    类名::~类名(){} 类外实现。

    代码

    class Animal {
    public:
    
    	Animal()
    	{
    		cout << "Animal 构造函数调用!" << endl;
    	}
    	virtual void Speak() = 0;
    
    	//析构函数加上virtual关键字,变成虚析构函数
    	//virtual ~Animal()
    	//{
    	//	cout << "Animal虚析构函数调用!" << endl;
    	//}
    
    
    	virtual ~Animal() = 0;
    };
    
    Animal::~Animal()
    {
    	cout << "Animal 纯虚析构函数调用!" << endl;
    }
    
    //和包含普通纯虚函数的类一样,包含了纯虚析构函数的类也是一个抽象类。不能够被实例化。
    
    class Cat : public Animal {
    public:
    	Cat(string name)
    	{
    		cout << "Cat构造函数调用!" << endl;
    		m_Name = new string(name);
    	}
    	virtual void Speak()
    	{
    		cout << *m_Name <<  "小猫在说话!" << endl;
    	}
    	~Cat()
    	{
    		cout << "Cat析构函数调用!" << endl;
    		if (this->m_Name != NULL) {
    			delete m_Name;
    			m_Name = NULL;
    		}
    	}
    
    public:
    	string *m_Name;
    };
    
    void test01()
    {
    	Animal *animal = new Cat("Tom");
    	animal->Speak();
    
    	//通过父类指针去释放,会导致子类对象可能清理不干净,造成内存泄漏
    	//怎么解决?给基类增加一个虚析构函数
    	//虚析构函数就是用来解决通过父类指针释放子类对象
    	delete animal;
    }
    
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    

    总结:

    ​ 1. 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象(因为子类属性在堆区开辟了空间,而父类只能delete父类自己的空间,而无法进入到子类去析构delete子类属性的空间

    ​ 2. 如果子类中没有堆区数据,可以不写为虚析构或纯虚析构

    ​ 3. 拥有纯虚析构函数的类也属于抽象类

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,311
精华内容 9,324
关键字:

c++多态

c++ 订阅