声明虚函数的一般格式如下:virtual函数类型函数名(参数表)其中,用关键词virtual声明的函数称为虚函数。如果一个成员函数被声明为虚函数,这就意味着该成员函数在派生类中可能有不同的实现。动态绑定只能通过指针或引用标识对象来调用虚函数。......
2023-11-07
虚函数是动态绑定的基础,什么时候将一个成员函数声明为虚函数,首先要看成员函数所在的类是否为基类,然后看该成员函数在其派生类中是否需要修改功能,最后看该成员函数的调用是否需要通过基类指针或引用(形参)去访问,若满足以上三点,则将该成员函数设置为虚函数。
在设置虚函数时必须注意以下几点:
(1)只有类的成员函数才能声明为虚函数。这是因为虚函数仅适用于有继承关系的类对象,所以普通函数不能声明为虚函数。
(2)静态成员函数不能是虚函数,因为静态成员函数不受限于某个对象。
(3)内联函数不能是虚函数,因为内联函数是不能在运行中动态确定其位置的。即使虚函数在类的内部定义,编译时仍将其看作是非内联的。
(4)构造函数不能是虚函数,因为构造时对象还是一片未定型的空间。只有在构造完成后,对象才能成为一个类的名副其实的实例。
(5)析构函数可以是虚函数,而且通常声明为虚函数。声明虚析构函数的目的在于:使用delete运算符删除一个对象时,能确保析构函数被正确地执行。这是因为设置虚析构函数后,可以利用动态绑定方式选择析构函数。
(6)一般要求基类中声明了虚函数后,派生类声明的虚函数应该与基类中虚函数的参数个数相等,对应参数的类型相同。如果不相同,则被派生类虚函数的参数类型强制转换为基类中虚函数的参数类型。
【例7.4】分析以下程序的执行结果。
解:上述程序中,父类Base中的析构函数为虚函数,子类Derived中的析构函数也为虚函数。执行结果如下:
调用Derived∷~Derived()
调用Base∷~Base()
在本例程序中,如果类Base中的析构函数不用虚函数,则执行结果如下:(www.chuimin.cn)
调用Base∷~Base()
这是因为基类的析构函数声明为虚函数时,调用f(ptr)函数执行delete ptr;语句时采用动态绑定,调用它基类的析构函数,所以输出上述结果。当不将基类的析构函数声明为虚函数时,delete隐含着对析构函数的调用,也就是不调用它基类的析构函数。
【例7.5】分析以下程序的执行结果。
解:在编译上述程序时,对类Derived中的virtual void display(double b)函数给出以下警告:
warning C4244:'argument':conversion from'const double'to'int',possible loss of data(从'const double'到'int'的数据转换可能丢失数据)
在忽略警告信息后(警告信息不影响程序的运行),执行本程序出现以下结果:
Base∷display a=10
从执行结果可以看到,该虚函数的调用好像未采用动态绑定。这是因为,类Derived从类Base派生,而其中虚函数display的参数与基类中的不同,所以强制执行基类的display()函数。若将类Derived中的display()虚函数改为:
virtual void display(int a)
则执行结果如下:
Derived∷display b=10
有关C++程序设计基础教程的文章
声明虚函数的一般格式如下:virtual函数类型函数名(参数表)其中,用关键词virtual声明的函数称为虚函数。如果一个成员函数被声明为虚函数,这就意味着该成员函数在派生类中可能有不同的实现。动态绑定只能通过指针或引用标识对象来调用虚函数。......
2023-11-07
声明函数模板的一般格式如下:template<模板参数表>函数返回值类型函数模板名(形参表)函数模板定义由关键字template开头,表示声明一个模板。模板参数表写在尖括号<>中,参数一般由关键字class或typename后加一个标识符构成。Class和typename的意义相同,表示后面的标识符是一个参数类型,代表一个潜在的标准类型或用户定义的类型。例如,定义max函数模板求两个数中的较大者。如下面的声明是错误的:可以看出,用函数模板比函数重载更方便,程序更简洁。......
2023-11-07
当定义类对象时,构造函数会自动执行。因为一个类可能会有包括默认构造函数在内的不止一种构造函数,下面讨论如何调用特定的构造函数。在这种情况下,会执行默认的构造函数,从而将sa的数据成员初始化为0。如果参数的类型和顺序不与任何构造函数相匹配,则C++将使用类型转换并寻找最佳匹配。......
2023-11-07
静态成员函数与静态数据成员类似,也是属于类的。与一般成员函数类似,静态成员函数也有访问限制,私有静态成员函数不能由外界访问。解:本程序的执行结果如下:s=5程序中定义对象a时,通过构造函数使静态数据成员n=2,在定义对象b时,通过构造函数使静态数据成员n=5,再执行MyClass2∷add()语句使全局变量s=5。这样共执行构造函数5次,n累计为5。......
2023-11-07
虚基类的声明是用在指定派生类时,放在派生类名的后面。该指针被称为虚基类指针。解:上述程序中,各类之间构成类层次如图6.14所示,其中虚线表示是虚继承,也就是说,其基类为虚基类。......
2023-11-07
为此,C++提供了一个更好的方法,就是利用类的构造函数来初始化类的数据成员。构造函数具有如下几个特点:构造函数名与类名相同,且没有返回值,不能指定函数类型。构造函数通常被声明为公有属性,但它不能像其他成员函数那样被显式地调用,它是在创建对象时被系统自动调用的。例如,可以将例2.1的MyClass类扩展为MyClass2,使其包含两个构造函数:上述类中包含两个构造函数:一个没有参数,另一个有两个参数。......
2023-11-07
所以,在定义派生类的构造函数时除了对自己的数据成员进行初始化外,还必须负责调用基类构造函数使基类的数据成员得以初始化。如果派生类中还有子对象,还应包含对子对象初始化的构造函数。最后执行派生类的构造函数。其中,如果派生类新增成员中有某个类的子对象,第步的调用才会执行,否则就直接跳转到第步,执行派生类的构造函数。在某些情况下,派生类构造函数的函数体可能为空,仅起到参数传递作用。......
2023-11-07
程序设计是指设计、编写和调试程序的方法与过程。由于程序是软件的本体,因此软件的质量主要通过程序的质量体现,因此,研究一种切实可行的程序设计方法至关重要。继承是面向对象程序设计方法的一个重要标志,利用继承机制可以大大提高程序的可重用性和可扩充性。......
2023-11-07
相关推荐