鱼C论坛

 找回密码
 立即注册
查看: 1377|回复: 6

[已解决]对象多态和方法多态(c++)

[复制链接]
发表于 2023-8-4 22:18:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
有高手能(用c++)详细讲一下对象多态和方法多态吗      概念模糊还是搞不懂搞不清  关于这个我网上也不怎么能查到
可以讲一下他们都是如何实现多态的 他们的区别是什么

如果可以的话能再讲一下虚函数的实现机制吗


最佳答案
2023-10-9 17:55:32
本帖最后由 鱼儿游游 于 2023-10-9 18:38 编辑

一、什么是多态:
C++中多态这个概念,就是程序运行时,父类指针可以根据具体指向的子类对象,来执行不同的函数,表现为多态。

二、实现多态的必要性原则:
1、父类必须存在虚函数(或纯虚函数)。
2、子类必须采用 public 方式继承父类。
3、必须通过父类的指针或者引用,调用虚函数。

三、详见以下示例:
#include <iostream>
using namespace std;

// 基类(父类):画图抽象类(父类必须存在虚函数)
class Shape {
        public:
                // 父类必须要有虚函数(加上 virtual 关键字),也可以是纯虚函数。
                virtual void draw() {
                        cout << "这是画图的接口!" << endl;
                };
};

// 派生类(子类):实现【画圆】的功能(子类必须采用public继承父类)
class Circle : public Shape {
        public:
                // 子类可以没有 virtual 关键字
                void draw() {
                        cout << "画一个圆!" << endl;
                }
};

// 派生类(子类):实现【画矩形】的功能(子类必须采用public继承父类)
class Rect : public Shape {
        public:
                void draw() {
                        cout << "画一个矩形!" << endl;
                }
};

// 派生类(子类):实现【画三角形】的功能(子类必须采用public继承父类)
class Triangle : public Shape {
        public:
                void draw() {
                        cout << "画一个三角形!" << endl;
                }
};

/* 测试多态 */
void testPolymorphism() {

        Shape *p = NULL;   // 创建一个基类(父类)的指针

        /*
          多态的表现形式一: 调用哪个虚函数,取决于【指针对象指向】哪种类型的对象。
            1、「派生类的指针」可以赋给「基类指针」;
            2、通过基类指针调用基类和派生类中的同名「虚函数」时:
               若该指针指向一个【基类的对象】,  那么被调用的是【基类的虚函数】;
               若该指针指向一个【派生类的对象】,那么被调用的是【派生类的虚函数】。
         */

        //【多态的表现形式一】示例:
        Circle c;
        p = &c;     // 指针 p 指向:派生类(子类):Circle
        p->draw();  // 调用哪个虚函数取决于 p 指向哪种类型的对象。此处调用的是:派生类(子类)Circle 中的 draw()

        Rect r;
        p = &r;
        p->draw();  // 此处调用的是:派生类(子类)Rect 中的 draw()

        Triangle t;
        p = &t;
        p->draw();  // 此处调用的是:派生类(子类)Triangle 中的 draw()

        Shape s;
        p = &s;
        p->draw();  // 此处调用的是:基类(父类)Shape 中的 draw()

        /*
          多态的表现形式二:  调用哪个虚函数,取决于【引用的对象】是哪种类型的对象。
            1、派生类的对象可以赋给基类「引用」
            2、通过基类引用调用基类和派生类中的同名「虚函数」时:
               若该引用引用的是一个基类的对象,那么被调 用是基类的虚函数;
               若该引用引用的是一个派生类的对象,那么被 调用的是派生类的虚函数。
         */

        //【多态的表现形式二】示例:
        Circle c2;
        Shape &s2 = c2;  // s2 引用的对象是 Circle 类对象
        s2.draw();       // 此处调用的是:派生类(子类)Circle 中的 draw()
}

/* 主程序 */
int main() {

        /**
         * 一、多态的定义:就是程序运行时,父类指针可以根据具体指向的子类对象,来执行不同的函数。
         * 二、多态的必要性原则:
         *     1、父类必须存在虚函数(或纯虚函数)。
         *     2、子类必须采用 public 方式继承父类。
         *     3、必须通过父类的指针或者引用,调用虚函数。
         */

        testPolymorphism(); // 测试多态
        return 0;

}

/*
  程序运行,输出显示如下:

    画一个圆!
    画一个矩形!
    画一个三角形!
    这是画图的接口!
    画一个圆!

 */
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-8-4 22:18:36 | 显示全部楼层

回帖奖励 +30 鱼币

对象多态方法多态都是C++中的多态概念,用于实现面向对象编程中的灵活性和可扩展性。

对象多态(也称为运行时多态)是指在父类和子类之间存在继承关系时,可以通过父类指针或引用来访问子类对象,并根据实际对象的类型调用相应的成员函数。这样可以在编译期间不确定具体对象的类型,而在运行时动态地确定调用哪个函数。

方法多态(也称为编译时多态)是指在同一个类中存在多个同名的函数,但它们的参数类型、个数或顺序不同,从而可以根据不同的参数类型和个数来选择合适的函数进行调用。这样可以根据函数的实际参数类型来进行函数重载,使代码更加灵活。

实现对象多态的关键是通过使用虚函数和基类指针或引用。在C++中,通过在基类中将函数声明为虚函数(使用virtual关键字),然后在派生类中进行重写(使用override关键字),可以实现虚函数的多态行为。当使用基类指针或引用指向子类对象时,可以根据实际对象的类型来调用对应的重写函数。

虚函数的实现机制是通过使用虚函数表(vtable)来实现的。每个包含虚函数的类都会生成一个虚函数表,其中存储了指向相应虚函数的函数指针。当通过基类指针或引用调用虚函数时,实际上是根据对象的虚函数表来确定要调用的函数地址,并进行动态绑定。

区别:
- 对象多态是通过继承和虚函数来实现的,允许以父类指针或引用调用子类的成员函数。
- 方法多态是通过函数重载来实现的,同一个类中存在多个同名但参数不同的函数。

总结起来,对象多态和方法多态都是C++中实现多态性的方式,对象多态通过虚函数和基类指针或引用实现,方法多态则通过函数重载实现。它们在实现机制和使用场景上有所区别,但都能提供灵活性和可扩展性的编程特性。

如果回答对你有帮助,请给我一个最佳答案!这对我非常重要!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-4 22:18:53 | 显示全部楼层

回帖奖励 +30 鱼币

对象多态方法多态都是C++中的多态概念,它们都可以通过虚函数来实现。下面我会详细解释它们的概念和实现方式,以及它们之间的区别。

对象多态,也称为运行时多态,是指在程序运行时根据对象的实际类型来确定调用的函数实现。简单来说,对象多态使得一个指针变量可以指向不同的派生类对象,并且通过这个指针调用的虚函数会根据实际对象的类型来确定执行哪个版本的函数。

下面是一个示例代码来演示对象多态的实现:
#include <iostream>class Animal {public:    virtual void sound() {        std::cout << "Animal makes a sound" << std::endl;    }};class Cat : public Animal {public:    void sound() {        std::cout << "Cat says: Meow!" << std::endl;    }};class Dog : public Animal {public:    void sound() {        std::cout << "Dog says: Woof!" << std::endl;    }};int main() {    Animal* animalPtr;    Cat cat;    Dog dog;    animalPtr = &cat;    animalPtr->sound(); // 输出:Cat says: Meow!    animalPtr = &dog;    animalPtr->sound(); // 输出:Dog says: Woof!    return 0;}
在上面的代码中,基类Animal有一个虚函数sound(),派生类CatDog分别重写了这个虚函数。在main()函数中,我们通过基类指针animalPtr分别指向Cat对象和Dog对象,并调用sound()函数。

由于sound()函数是虚函数,并且在基类中被声明为虚函数,所以在运行时会根据实际对象的类型来确定调用哪个版本的函数。这就实现了对象多态。

方法多态,也称为编译时多态,是指在编译阶段根据函数的参数类型或者表达式的静态类型来确定调用的函数实现。方法多态通过函数重载和模板特化来实现。

下面是一个示例代码来演示方法多态的实现:
#include <iostream>// 函数重载void print(int num) {    std::cout << "Printing an integer: " << num << std::endl;}void print(float num) {    std::cout << "Printing a float: " << num << std::endl;}int main() {    int intNum = 10;    float floatNum = 3.14;    print(intNum); // 输出:Printing an integer: 10    print(floatNum); // 输出:Printing a float: 3.14    return 0;}
在上面的代码中,通过函数重载实现了方法多态。print()函数被定义了两个不同的版本,分别接受int类型和float类型的参数。根据传入的参数类型,编译器在编译阶段会确定调用哪个版本的函数。

总结一下:

- 对象多态是通过虚函数实现的,它使得一个指针变量可以指向不同的派生类对象,并且调用虚函数时根据对象的实际类型来确定执行哪个版本的函数。
- 方法多态是通过函数重载和模板特化实现的,它根据函数的参数类型或者表达式的静态类型在编译阶段确定调用哪个版本的函数。

对于虚函数的实现机制,C++使用了虚函数表(vtable)来支持多态性。每个包含虚函数的类都有一个虚函数表,其中存储了该类及其派生类中所有虚函数的地址。当调用虚函数时,通过对象的虚函数指针(vptr)查找对应的虚函数表,并通过表中的偏移量来调用正确的函数。

希望以上解释能帮助你更好地理解对象多态、方法多态以及虚函数的实现机制。

如果回答对你有帮助,请给我一个最佳答案!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-4 22:18:53 | 显示全部楼层

回帖奖励 +30 鱼币

对象多态和方法多态是面向对象编程中的两个重要概念。对象多态指的是通过基类指针或引用来调用派生类对象的方法,实现了基类和派生类之间的接口统一性。方法多态指的是同名的方法在不同的对象上表现出不同的行为。

对象多态的实现是通过在基类中定义虚函数,然后在派生类中重写该虚函数来实现的。当通过基类指针或引用调用虚函数时,会根据实际指向的对象类型来确定调用的是哪个函数,从而实现了多态性。这样一来,即使基类指针或引用指向的是派生类对象,也能够调用到派生类中重写的虚函数。

方法多态的实现是通过函数重载和函数重写来实现的。函数重载指的是在同一个类中定义多个同名函数,但参数列表不同,从而实现了同名函数在不同对象上的多态性。函数重写指的是在派生类中重新定义基类中的虚函数,从而实现了派生类对象在调用虚函数时可以表现出不同的行为。

虚函数的实现机制是通过在类的虚函数表中存储函数指针来实现的。每个包含虚函数的类都有一个虚函数表,其中存储了该类的虚函数的地址。当通过基类指针或引用调用虚函数时,会根据对象的实际类型在虚函数表中查找对应的函数指针,然后调用该函数。

总结一下,对象多态和方法多态都是通过在基类中定义虚函数来实现的,但实现机制和表现形式有所不同。对象多态通过基类指针或引用来调用派生类对象的方法,实现了接口的统一性;方法多态通过函数重载和函数重写来实现,同名函数在不同对象上表现出不同的行为。虚函数的实现机制是通过虚函数表来实现的,根据对象的实际类型在虚函数表中查找对应的函数指针来调用虚函数。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-19 19:41:49 | 显示全部楼层
可能全是GPT!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-10-9 15:39:08 | 显示全部楼层
清楚的一批
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-10-9 17:55:32 | 显示全部楼层    本楼为最佳答案   
本帖最后由 鱼儿游游 于 2023-10-9 18:38 编辑

一、什么是多态:
C++中多态这个概念,就是程序运行时,父类指针可以根据具体指向的子类对象,来执行不同的函数,表现为多态。

二、实现多态的必要性原则:
1、父类必须存在虚函数(或纯虚函数)。
2、子类必须采用 public 方式继承父类。
3、必须通过父类的指针或者引用,调用虚函数。

三、详见以下示例:
#include <iostream>
using namespace std;

// 基类(父类):画图抽象类(父类必须存在虚函数)
class Shape {
        public:
                // 父类必须要有虚函数(加上 virtual 关键字),也可以是纯虚函数。
                virtual void draw() {
                        cout << "这是画图的接口!" << endl;
                };
};

// 派生类(子类):实现【画圆】的功能(子类必须采用public继承父类)
class Circle : public Shape {
        public:
                // 子类可以没有 virtual 关键字
                void draw() {
                        cout << "画一个圆!" << endl;
                }
};

// 派生类(子类):实现【画矩形】的功能(子类必须采用public继承父类)
class Rect : public Shape {
        public:
                void draw() {
                        cout << "画一个矩形!" << endl;
                }
};

// 派生类(子类):实现【画三角形】的功能(子类必须采用public继承父类)
class Triangle : public Shape {
        public:
                void draw() {
                        cout << "画一个三角形!" << endl;
                }
};

/* 测试多态 */
void testPolymorphism() {

        Shape *p = NULL;   // 创建一个基类(父类)的指针

        /*
          多态的表现形式一: 调用哪个虚函数,取决于【指针对象指向】哪种类型的对象。
            1、「派生类的指针」可以赋给「基类指针」;
            2、通过基类指针调用基类和派生类中的同名「虚函数」时:
               若该指针指向一个【基类的对象】,  那么被调用的是【基类的虚函数】;
               若该指针指向一个【派生类的对象】,那么被调用的是【派生类的虚函数】。
         */

        //【多态的表现形式一】示例:
        Circle c;
        p = &c;     // 指针 p 指向:派生类(子类):Circle
        p->draw();  // 调用哪个虚函数取决于 p 指向哪种类型的对象。此处调用的是:派生类(子类)Circle 中的 draw()

        Rect r;
        p = &r;
        p->draw();  // 此处调用的是:派生类(子类)Rect 中的 draw()

        Triangle t;
        p = &t;
        p->draw();  // 此处调用的是:派生类(子类)Triangle 中的 draw()

        Shape s;
        p = &s;
        p->draw();  // 此处调用的是:基类(父类)Shape 中的 draw()

        /*
          多态的表现形式二:  调用哪个虚函数,取决于【引用的对象】是哪种类型的对象。
            1、派生类的对象可以赋给基类「引用」
            2、通过基类引用调用基类和派生类中的同名「虚函数」时:
               若该引用引用的是一个基类的对象,那么被调 用是基类的虚函数;
               若该引用引用的是一个派生类的对象,那么被 调用的是派生类的虚函数。
         */

        //【多态的表现形式二】示例:
        Circle c2;
        Shape &s2 = c2;  // s2 引用的对象是 Circle 类对象
        s2.draw();       // 此处调用的是:派生类(子类)Circle 中的 draw()
}

/* 主程序 */
int main() {

        /**
         * 一、多态的定义:就是程序运行时,父类指针可以根据具体指向的子类对象,来执行不同的函数。
         * 二、多态的必要性原则:
         *     1、父类必须存在虚函数(或纯虚函数)。
         *     2、子类必须采用 public 方式继承父类。
         *     3、必须通过父类的指针或者引用,调用虚函数。
         */

        testPolymorphism(); // 测试多态
        return 0;

}

/*
  程序运行,输出显示如下:

    画一个圆!
    画一个矩形!
    画一个三角形!
    这是画图的接口!
    画一个圆!

 */
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-5 23:21

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表