C++虚函数、静态变量

    xiaoxiao2021-03-25  83

    虚函数是在类中被声明为virtual的成员函数,当编译器看到通过指针或引用调用此类函数时,对其执行动态联编,即通过指针(或引用)指向的类的类型信息来决定该函数是哪个类的。通常此类指针或引用都声明为基类的,它可以指向基类或派生类的对象。多态指同一个方法根据其所属的不同对象可以有不同的行为。 虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数 1、录入下面程序,并分析结果:

    #include <iostream> #include <complex> using namespace std; class Base { public: Base() {cout<<"Base-ctor"<<endl;} ~Base() {cout<<"Base-dtor"<<endl;} virtual void f(int){cout<<"Base::f(int)"<<endl;} virtual void f(double){cout<<"Base::f(double)"<<endl;} virtual void g(int i=10){cout<<"Base::g()"<<i<<endl;} }; class Derived : public Base { public: Derived() {cout<<"Derived-ctor" <<endl;} ~Derived(){cout<<"Derived-dtor"<<endl;} void f(complex<double>) { cout<<"Derived::f(complex)"<<endl; } void g(int i=20){ cout<<"Derived::g()"<<i<<endl; } }; int main() { cout<<sizeof(Base)<<endl; cout<<sizeof(Derived)<<endl; Base b; Derived d; Base *pb=new Derived; b.f(1.0); d.f(1.0); pb->f(1.0); b.g(); d.g(); pb->g(); delete pb; return 0; }

    分析:从实验结果可以看出来两个类的字节数都是8,因为在基类base中有虚函数就会创建一个虚函数的函数指针表(该表指向虚函数),在类中会创建一个指针指向该表占8个字节(devc++在64位操作系统中指针是8个字节)。Derived是从base继承下来的,没有增加新的数据成员,所以依然是8个字节。Base b; Derived d; 创建基类的对象,首先调用基类的构造函数,在创建派生类的对象时,先调用基类构造函数再调用派生类的构造函数。Base *pb=new Derived;这个的意思是定义一个基类的指针,构建一个派生类的对象赋值给基类指针,构建派生类的对象会先调用构造函数然后再调用派生类的构造函数。b.f(1.0); 这句话调用基类的f函数,调用的是参数类型为double的函数,d.f(1.0);调用派生类的f函数。 pb->f(1.0); 这句话因为pb是基类指针,而派生类的f函数参数和基类的f函数参数不同,所以使用pd指针调用f应该调用的是基类的f函数,b.g(); d.g(); 这两句是分别调用基类和派生类的g函数pb->g();这句话是调用派生类的g函数,因为基类是虚函数,所以会调用派生类,但是因为函数参数是静态绑定的,所以参数依然是10。delete pb; 释放空间的时候正好和构造函数相反,先释派生类的构造函数,然后释放对象的析构函数,最后调用基类的析构函数。

    2、录入下面程序,分析运行结果:

    #include <iostream> using namespace std; class Base { public: Base():data(count) { cout<<"Base-ctor"<<endl; ++count; } ~Base() { cout<<"Base-dtor"<<endl; --count; } static int count; int data; }; int Base::count; class Derived : public Base { public: Derived():data(count),data1(data) { cout<<"Derived-ctor"<<endl; ++count; } ~Derived() { cout<<"Derived-dtor"<<endl; --count; } static int count; int data1; int data; }; int Derived::count=10; int main() { cout<<sizeof(Base)<<endl; cout<<sizeof(Derived)<<endl; Base* pb = new Derived[3]; cout<<pb[2].data<<endl; cout<<((static_cast<Derived*>(pb))+2)->data1<<endl; delete[] pb; cout<<Base::count<<endl; cout<<Derived::count<<endl; return 0; }

    分析:开始求base类的字节数静态变量不占字节数,所以只有int型的data占四个字节,派生类的数据成员新增加了data和data1成员,所以占有的字节数应该是12个字节,Base* pb = new Derived[3];定义了base类的指针pb,又新建了一个derived类数组有三个对象,pb指向这个对象数组,在构造对像时,先要调用基类的构造函数,在调用派生类的构造函数。cout (省略两个<,连打两次<就出问题,什么鬼) pb[2].data (省略两个<) endl;因为base类是占有四个字节,而derived占有十二个字节,所以指针调用的时候一次只跳了四个字节,pb[2]并不指向的是derived类的第二个对象,输出来的值仅仅是第一个对象的第8-12空间中储存的值。倒数第七句;这句话因为在derived类中定义数据成员的时候,先定义了data1,所以先将data赋值给data1,但是此时,data还没有被赋值,故data1是随机值。delete[] pb;在释放pb的空间的时候,因为它是base的指针,没有将基类析构函数设置为虚析构函数,所以释放空间的时候只调用了base类的指针,而derived类的析构函数没有被调用。cout(省略两个<)Base::count(省略两个<)endl;这句话是直接输出base中count,静态变量如果没有被赋值的话默认的就是0,cout(省略两个<)Derived::count(省略两个<)endl;而derived调用了三次构造函数,所以count的值是13。

    转载请注明原文地址: https://ju.6miu.com/read-16111.html

    最新回复(0)