C++ : 继承问题 [virtual函数调用,为什么禁止在virtual使用默认参数]

news/2024/9/20 7:13:45 标签: c++

文章目录

  • 子类指针,父类指针分别调用virtual函数,与非virtual函数
  • 虚函数中尽量不要使用默认参数!!!

子类指针,父类指针分别调用virtual函数,与非virtual函数

virtual函数,通过指针调用的是子类函数
非virtual函数,取决于指针的类型

class Person {
public:
    void Print()
    {
        cout << "Person" << endl;
    }
    virtual void VirtualPrint()
    {
        cout << "VirtualPrint Person" << endl;
    }
};

class Studen : public Person {
public:
    void Print()
    {
        cout << "Student" << endl;
    }
    virtual void VirtualPrint()
    {
        cout << "VirtualPrint Student" << endl;
    }
};

int main()
{
    Person *p = new Studen();
    Studen *s = new Studen();
    p->Print();     // Person
    s->Print();     // Student
    p->VirtualPrint();  // VirtualPrint Student
    s->VirtualPrint();  // VirtualPrint Student
    return 0;
}

虚函数中尽量不要使用默认参数!!!

class Father {
public:
    void func1(int val = 100){
        cout << "Father \t: func1" << "\t" << val << endl;
    }
    virtual void func2virtual(int val = 100){
        cout << "Father \t: func2" << "\t" << val << endl;
    }
};

class Son : public Father {
public:
    void func1(int val = 200){
        cout << "Son \t: func1" << "\t" << val << endl;
    }
    virtual void func2virtual(int val = 200){
        cout << "Son \t: func2" << "\t" << val << endl;
    }
};

当指针类型与实体类型一致时,很容易分清楚其调用规则

void group1()
{
    Father *f = new Father();
    Son *s = new Son();
    f->func1();
    s->func1();
    // Father  : func1 100
    // Son     : func1 200

    f->func1(300);
    s->func1(300);
    // Father  : func1 300
    // Son     : func1 300

    f->func2virtual();
    s->func2virtual();
    // Father  : func2 100
    // Son     : func2 200

    f->func2virtual(300);
    s->func2virtual(300);
    // Father  : func2 300
    // Son     : func2 300
}

当指针类型与实体类型不一致时,很不容易分清楚其调用规则
在virtual函数中使用默认参数,因为virtual是动态绑定,导致都是调用了子类函数,但是默认参数是根据指针类型来使用的

void group2()
{
    Father *f = new Son();
    Son *s = new Son();
    f->func1();
    s->func1();
    // Father  : func1 100
    // Son     : func1 200

    f->func1(300);
    s->func1(300);
    // Father  : func1 300
    // Son     : func1 300

    // virtual func use dynamic func, but use ptr default args
    // 重点处
    f->func2virtual();
    s->func2virtual();
    // Son     : func2 100
    // Son     : func2 200

    // virtual func use dynamic func, use given args
    f->func2virtual(300);
    s->func2virtual(300);
    // Son     : func2 300
    // Son     : func2 300
}

http://www.niftyadmin.cn/n/5666801.html

相关文章

有毒有害气体检测仪的应用和性能_鼎跃安全

随着现代工业的不断发展和扩张&#xff0c;越来越多的企业涉及到有毒有害气体的生产、使用和处理。工业规模的扩大导致有毒有害气体的排放量增加&#xff0c;同时也增加了气体泄漏的风险。在发生火灾、爆炸或危险化学品泄漏等紧急事件时&#xff0c;救援人员需要迅速了解现场的…

【tomcat】tomcat学习笔记

文章目录 1.tomcat乱码问题1.1 linux乱码中文显示乱码问号问题1.2windows乱码1.2.1 方式一1.2.2方式二 1.3 Idea中运行tomcat乱码问题 2. 获取tomcat启动端口号3. idea运行tomcat 的配置问题4.dockerfile构建tomcat镜像问题4.1 替换端口号 5.启动多个tomcat方法6.修改tomcat JA…

汽车焊机数据通信:Profinet转Canopen网关的神奇连接

在汽车制造领域&#xff0c;汽车焊机的高效、稳定运行对于整车质量至关重要。而Profinet转Canopen网关在汽车焊机的数据通信中发挥着关键作用。 Profinet是一种广泛应用于工业自动化领域的通信协议&#xff0c;具有高速、实时、可靠等特点。Canopen则在汽车电子等领域有着广泛…

JSONC:为JSON注入注释的力量

JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;广泛应用于Web开发、配置文件和数据存储等领域。 其简洁的语法和易于解析的特点&#xff0c;使得JSON成为了现代编程中不可或缺的一部分。然而&#xff0c;JSON的一个显著缺点是…

Delphi5利用DLL实现窗体的重用

文章目录 效果图参考利用DLL实现窗体的重用步骤1 设计出理想窗体步骤2 编写一个用户输出的函数或过程&#xff0c;在其中对窗体进行创建使它实例化步骤3 对工程文件进行相应的修改以适应DLL格式的需要步骤4 编译工程文件生成DLL文件步骤5 在需要该窗体的其他应用程序中重用该窗…

React + Vite 多环境配置

1.根目录创建文件&#xff1a; .env.dev //测试环境 .env.development //本地环境 .env.production //正式环境 .env.uat //预发布环境 注&#xff1a;变量名必须使用 VITE_API 开头 2.package.json 配置&#xff1a; --mode 设置读取制定 .env文件 &#xff0c;默认读取.en…

Java-Day02学习

Java-Day02 一维数组 1.声明数组 int[ ] a; //声明数组时不规定数组长度 2.分配空间 a new int[5]; //分配空间: 告诉计算机分配几个连续的空间。eg:scores new int[30]; avgAge new int[6]; name new String[30]; 3.赋值 a [0] 8; //向分配的格子里放数…

在WPF中自定义控件时如何选择基类

在WPF中需要自定义控件&#xff0c;首要要选择需要继承的基类 FrameworkElement 这是常用的最低级的基类。通常&#xff0c;只有当希望重写OnRender()方法并使用DrawingContext从头绘制内容时&#xff0c;才会继承该类。 Control 当从头开始创建控件时&#xff0c;这是最常用…