精华内容
下载资源
问答
  • 基类构造函数调用虚函数的处理——之构造流程
    千次阅读
    2019-05-15 14:55:18

    当基类构造函数调用虚函数时,不会调用派生类的虚函数。

    现有基类A和派生类B,两个类中有虚成员函数 test()。程序刚进入B b时,在执行派生类B的构造函数时,需要首先调用基类A的构造函数。

    那么调用的是哪个构造函数呢?根据派生类构造函数原理:

    这里基类A有两个构造函数A() :m() { test(); }和 A(int x) :m(x) { test(); },派生类B中初始化构造函数中基类A时,使用的是 B() :A(2){ test(); },所以调用基类A的构造函数 是A(int x) :m(x) { test(); }。

    现在继续分析:进入构造函数 A(int x) :m(x) { test(); }后,先初始化m,后进入函数体,执行test()。这里执行的是类A中的test(),因为:当基类被构造时,对象还不是一个派生类的对象。当类A构造函数执行完毕后,在返回类B构造函数体,执行test()。这里执行的就是类B中的test()了。

    #include<iostream>

    using namespace std;

    class A {
    public:
        A() :m() { test(); }          //构造函数
        A(int x) :m(x)                //构造函数
        {
            test(); 
        }
        virtual void test() { cout << m << ' '; }
        int m;
    };

    class B :public A {
    public:
        B() :A(2){ test(); }
        virtual void test() { cout << m << ' '; }
    };


    int main() {
        B b;         //进入类B,先初始化类A中的内容,后执行本类B的函数体
        A *p = &b;
        p->test();

        return 0;
    }

    更多相关内容
  • 每个类中存在虚函数时,当构造一个对象时,系统会为对象分配相应的内存空间。但是虚函数表存放在程序的只读数据段中,在实例化对象时,编译器会自动在对象里安插一个指针vPtr指向虚函数表VTable; 下面看一个小例子...

    每个类中存在虚函数时,当构造一个对象时,系统会为对象分配相应的内存空间。但是虚函数表存放在程序的只读数据段中,在实例化对象时,编译器会自动在对象里安插一个指针vPtr指向虚函数表VTable;
    下面看一个小例子:

    #include<iostream>
    using namespace std;
    
    class A {
    public:
    	void f1() {
    		cout << "f1" << endl;
    	}
    	virtual void f2() {
    		cout << "f2" << endl;
    	}
    };
    
    int main() {
    	A* a = nullptr;
    	a->f1();
    	a->f2();
    
    	system("pause");
    	return 0;
    }
    

    此时a->f1();可以正常运行,a->f2();无法运行,报错如下:
    在这里插入图片描述
    推测,在构造对象a时,A* a = nullptr;,因为是空的,所以无法在栈区分配空间,自然指向虚函数表的指针就不存在了,所以无法找到虚函数表,来正确调用虚函数。

    那么,如果构造对象时,为其分配栈区的空间时,可以调用到虚函数吗??
    那就将A* a = nullptr;改为A* a = new A();,运行结果如下:
    在这里插入图片描述

    展开全文
  • A.h#ifndef A_H#define A_Hclass A{public: virtual void a(); virtual void b(); virtual void c();};#endifA.cpp#include &lt;iostream&gt;using std::cout;using std::endl;#include "...

    A.h

    #ifndef A_H
    #define A_H
    class A
    {
    public:

    virtual void a();
    virtual void b();
    virtual void c();
    };

    #endif


    A.cpp

    #include <iostream>
    using std::cout;
    using std::endl;
    #include "A.h"
    void A::a()
    {
    cout<<"in class A"<<endl;
    b();
    c();
    }
    void A::b()
    {
    cout<<"in class A, function b()"<<endl;
    }
    void A::c()
    {
    cout<<"in class A, function c()"<<endl;

    }


    B.h

    #ifndef B_H
    #define B_H
    #include "A.h"
    class B:public A 
    {
    public:

    virtual void b();
    virtual void c();

    };

    #endif

    B.cpp

    #include <iostream>
    using std::cout;
    using std::endl;

    #include "B.h"


    void B::b()
    {
    cout<<"in class B, function b()"<<endl;
    }
    void B::c()
    {
    cout<<"in class B, function c()"<<endl;

    }

    test.cpp

    #include <iostream>
    using std::cout;
    using std::endl;
    #include "A.h"
    #include "B.h"

    int main()
    {
    B bbb;

    A *ptra = 0;

    ptra = &bbb;

    ptra->a();

    }

    结果

    [root@hsm test_virtual_func]# ./test
    in class A
    in class B, function b()
    in class B, function c()

    展开全文
  • 在一个类的成员函数前面加virtual 关键字,在另一个类中不加virtual关键字,除此之外两类的成员完全相同,然后用sizeof()判断两类的大小。... virtual void func()//加virtual关键字声明为虚函数 { ...

    虚函数表指针 vptr 的存在

    • 编译器在编译时会为每个含有虚函数的类添加一个隐藏的虚函数表指针 vptr ,vptr 指针对程序员是不可见的,它用于指向虚函数表,虚函数表中有每个虚函数的入口地址。
    • 首先证明虚函数表指针 vptr 的存在。在一个类的成员函数前面加virtual 关键字,在另一个类中不加virtual关键字,除此之外两类的成员完全相同,然后用sizeof()判断两类的大小。

    代码如下:

    #include <iostream>
    
    class Parent1
    {
    public:
        int p1;
        virtual void func()//加virtual关键字声明为虚函数
        {
            std::cout << "调用了基类Parent1的func()" << std::endl;
        }
    };
    
    class Parent2
    {
    public:
        int p2;
        void func()//没有加virtual关键字声明
        {
            std::cout << "调用了基类Parent2的func()" << std::endl;
        }
    };
    
    int main()
    {
        std::cout << "sizeof(Parent1):" << sizeof(Parent1) << '\n'
                  << "sizeof(Parent2):" << sizeof(Parent2) << std::endl;
    
        return 0;
    }

    程序执行结果如下:
    这里写图片描述
    Parent1所占空间比Parent2多4个字节,这四个字节用来存储隐藏的指针成员变量,它指向虚函数表,虚函数表包含类中所有虚函数的地址,包括继承而来的虚函数。

    基类指针(或引用)指向派生类对象(或引用)时调用虚函数时,虚函数表指针调用虚函数的过程

    • 含有虚函数的基类对象和派生类对象都有vptr指针,每个类的vptr指针指向相应的虚函数表。基类指针(或引用)指向派生类对象(或引用)时调用虚函数时,派生类vptr指针找到虚函数表,根据虚函数表找到相应虚函数的入口地址,然后进行调用。这是动态联编。
    • 动态联编是指在程序运行的时候,编译器才去判断调用哪个函数或如何执行程序。如if-else结构、switch结构等。
    • 静态联编是指程序在编译阶段就确定了如何执行。
    展开全文
  • 第一种情况,当基类和子类中声明的是同名非虚函数时.调用关系如下 #include <iostream> using namespace std; #include <bits/stdc++.h> class AAA { public: void test1() { printf("This is AAA...
  • 基类指针pBase指向派生类对象basePlus,基类与派生类含有同名同参的函数,pBase调用函数应该调用哪个,当函数有虚函数时又该调用哪个? 先上结论: 基类指针pBase指向派生类对象basePlus时,基类与派生类都含有...
  • 虚函数基类与子类构造函数中调用虚函数。当生成子类对象时,函数的调用顺序是怎样的
  • C++ 基础之虚函数和虚基类

    千次阅读 2020-02-28 00:23:53
    C++ 基础之虚函数和虚基类 C++ 有别于 C ,比较重要的就是其抽象、封装、继承和多态等特性。多态又具体地体现在重载、虚函数和模板等等之上。 今天就和大家聊一聊虚函数和虚基类虚函数 我们来思考一个问题。假如子...
  • 在C++中,子类可以重载基类虚函数,这是C++语法中一个重要的多态。 例如,ClassB继承自ClassA,且重载了基类的一个函数,则被调用时将会触发重载的版本: #include<iostream> using namespace std; class ...
  • class Base { // 基类 public: virtual void f() { cout<<"Base"<<endl; } }; class Derived : public Base { // 派生类 public: virtual void f() { // 最好加上该virtual cout...
  • 在C++多态的实现是利用虚函数完成的,派生类对基类虚函数重写,通过基类的指针或引用调用虚函数来实现多态的特性。本问重点讨论为什么必须是通过基类的指针或引用调用虚函数才能构成多态?我们将按照如下顺序逐步...
  • C++ 继承对基类构造函数调用顺序的影响
  • 多态的使用方法是当基类指针指向派生类对象时,可以直接调用派生类重写的虚函数,而不是基类虚函数。实现方法也是老生常谈,通过每个对象中的虚函数表指针,去找属于自己类的虚函数执行。那如果用派生类指针指向...
  • 1、利用多态调用不同方法 //.h Class Base{ public: virtual ~Base() {}; virtual funcA(); funcB(); funcC(); } Class Child:Base{ public: virtual funcA(); funcB(); } //.cpp Base * ptr1 = new Base(); ...
  • c++中的 虚函数 纯虚函数 虚基类

    千次阅读 2018-06-27 21:23:06
    一、前言 原文转载自 ...虚函数是用于多态中virtual修饰父类函数,确保父类指针调用子类对象时,运行子类函数的。 2.纯虚函数是用来定义接口的,也就是基类...
  • 虚函数与虚基类

    千次阅读 2017-10-30 10:00:36
    1.虚函数是用于多态中virtual修饰父类函数,确保父类指针调用子类对象时,运行子类函数的。 2.纯虚函数是用来定义接口的,也就是基类中定义一个纯虚函数,基类不用实现,让子类来实现。 3.虚基类是用来在多...
  • 近来看了侯捷的《深入浅出MFC》,读到...因为书中说了这么一句:使用基类之指针”指向“派生类之对象”,由该指针只能调用基类所定义的函数,如果要让基类的指针使用派生类中定义的函数,就将该函数定义为虚函数
  • 本文实例讲述了Python基类函数的重载与调用方法。分享给大家供大家参考。具体分析如下: 刚接触Python语言的时间不长,对于这个语言的很多特性并不是很了解,有很多用法都是还不知道。今天想着写一个Python面向对象...
  • 创建Derived对象调用Derived构造函数,Derived构造函数中没有显示调用父类Base构造函数,但是创建Derived对象时依然会调用父类base的构造函数,故输出了Base和Derived构造信息。同样的通过动态分配内存创建Derived...
  • 就需要让基类的析构函数变为虚函数,否则执行delete的结果是不确定的 综合举例如下,实现了两个要求:一个是通过基类指针来访问到了派生类的函数,一个是使用虚析构函数,实现了通过基类指针删除所指派生类的对象: ...
  • 理解虚函数( virtual function )的几个关键点: 理解早绑定(early binding)、晚绑定(late binding)。所谓early binding:On compile ...所谓late binding:On compile time,函数(虚函数)的调用被搞成了:pObj-...
  • 解释某个函数,我通常的讲解不会先去长篇大论去空谈,先整个例子来看看!!走起.... #include #include string> using namespace std; class A { public: A(const char*s) { coutendl; } }; class B:...
  • C++ - 虚基类虚函数与纯虚函数

    千次阅读 多人点赞 2017-04-10 17:50:07
    转自:... 虚基类 在说明其作用前先看一段代码 classA { public: intiValue; }; classB:publicA { public: voidbPrintf(){cout<<"This is class B"<<...
  • 只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中全部都按原样保留下来了,在派生类外可以调用基类的公用成员函数访问基类的私有...
  • 通过对象调用虚函数,在编译阶段就能确定调用的是哪一个类的虚函数,所以属于静态关联,如果通过基类指针调用虚函数,在编译阶段无法从语句本身确定调用哪一个类的虚函数,只有在运行时,指针指向某一具体对象后,...
  • 多态性给我们带来了好处:多态使得我们可以通过基类的引用或指针来指明一个对象(包含其派生类的...一个函数说明为虚函数,表明在继承的类中重载这个函数时,当调用这个函数时应当查看以确定调用哪个对象的这个函数。
  • c++知识细节-基类指针指向子类对象/虚纯虚函数/多态性/虚析构 基类指针,派生类指针 新玩法: 父类指针可以new一个子类对象. ...虚函数 Q: 有没有一个解决方法,使我们只定义一个对象指针,就能调用各种子类
  • 必须先使用基类指针或者引用指向子类型对象,然后直接或者间接使用基类指针调用虚函数。 纯虚函数 是一种特殊的虚函数,它的一般格式如下:  class < 类名 > { virtual < 类型 > < 函数名 > ( ...
  • 这里添加了以B为直接基类的派生类D,仍以A类作为基类指针,但是最初只在B中声明的虚构函数的调用问题,明显,虚函数并没有起作用 这里添加了以B为直接基类的派生类D,以B类作为基类指针,但是最初只在B中声明的虚构...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 75,743
精华内容 30,297
关键字:

对虚函数使用基类类型的对象调用