当前位置: 首页 > news >正文

网站平台建设设备清单2012服务器如何做网站

网站平台建设设备清单,2012服务器如何做网站,wordpress 站内通知,h5商城网站是什么虚函数 什么是虚函数?虚函数示例解析代码解析: 使用虚函数的注意事项1. 虚函数的声明与定义2. 派生类中的虚函数 哪些函数不能声明为虚函数1. 普通函数(非成员函数)2. 构造函数3. 内联成员函数4. 静态成员函数5. 友元函数总结 纯虚…

虚函数

    • 什么是虚函数?
    • 虚函数示例解析
      • 代码解析:
    • 使用虚函数的注意事项
      • 1. 虚函数的声明与定义
      • 2. 派生类中的虚函数
    • 哪些函数不能声明为虚函数
      • 1. 普通函数(非成员函数)
      • 2. 构造函数
      • 3. 内联成员函数
      • 4. 静态成员函数
      • 5. 友元函数
      • 总结
    • 纯虚函数和抽象类
      • 示例
      • 输出结果
      • 作用
      • 使用场景
      • 注意事项
      • 示例代码解释

什么是虚函数?

虚函数是C++中实现多态性的关键机制。当指向基类的指针在操作它的多态类对象时,可以根据指向的不同类对象动态调用其相应的函数,这个函数就是虚函数。

在基类中定义虚函数后,可以在派生类中对虚函数进行重新定义,并且可以通过基类指针或引用,在程序运行阶段动态地选择调用基类和不同派生类中的同名函数。如果派生类中没有对虚函数重新定义,则它继承其基类的虚函数。

虚函数示例解析

让我们来分析一下给出的虚函数示例程序:

#include "stdafx.h"
#include<iostream>
using namespace std;class Base
{
public:virtual void Print()  // 基类虚函数{printf("This is Class Base!\n");}
};class Derived1 :public Base
{
public:void Print()  // 派生类1重写虚函数{printf("This is Class Derived1!\n");}
};class Derived2 :public Base
{
public:void Print()  // 派生类2重写虚函数{printf("This is Class Derived2!\n");}
};int main()
{Base Cbase;Derived1 Cderived1;Derived2 Cderived2;// 直接调用对象的方法Cbase.Print();Cderived1.Print();Cderived2.Print();cout << "---------------" << endl;// 通过基类指针调用方法Base *p1 = &Cbase;Base *p2 = &Cderived1;Base *p3 = &Cderived2;p1->Print();p2->Print();p3->Print();
}

程序输出:

This is Class Base!
This is Class Derived1!
This is Class Derived2!
---------------
This is Class Base!
This is Class Derived1!
This is Class Derived2!

代码解析:

  1. 首先,我们定义了一个基类 Base,其中包含一个虚函数 Print()
  2. 然后,我们定义了两个派生类 Derived1Derived2,它们都继承自 Base 并重写了 Print() 函数。
  3. main() 函数中,我们创建了三个对象:CbaseCderived1Cderived2
  4. 当我们直接调用对象的 Print() 方法时,每个对象都调用了自己类中定义的 Print() 函数。
  5. 然后,我们创建了三个基类指针,分别指向三个不同的对象。
  6. 关键在于:当我们通过基类指针调用 Print() 方法时,由于 Print() 是虚函数,程序会根据指针实际指向的对象类型来调用相应的函数。这就是多态的实现。

使用虚函数的注意事项

1. 虚函数的声明与定义

注意点: 只需要在声明函数的类体中使用关键字 virtual 将函数声明为虚函数,而定义函数时不需要使用关键字 virtual

具体例子:

// 正确的做法
class Animal {
public:virtual void makeSound(); // 在声明时使用virtual关键字
};// 定义时不需要使用virtual关键字
void Animal::makeSound() {cout << "Some generic animal sound" << endl;
}

在类外部定义虚函数时,不需要重复 virtual 关键字。如果类的声明和定义都在类体内,则只需要一次 virtual 关键字即可:

class Animal {
public:virtual void makeSound() { // 声明并定义,仅需一次virtual关键字cout << "Some generic animal sound" << endl;}
};

2. 派生类中的虚函数

注意点: 当将基类中的某一成员函数声明为虚函数后,派生类中的同名函数自动成为虚函数。

具体例子:

class Animal {
public:virtual void makeSound() {cout << "Some generic animal sound" << endl;}
};class Dog : public Animal {
public:// 此处无需使用virtual关键字,该函数自动成为虚函数void makeSound() {cout << "Woof!" << endl;}
};class Cat : public Animal {
public:// 同样,此处也无需使用virtual关键字void makeSound() {cout << "Meow!" << endl;}
};int main() {Animal* animals[3];animals[0] = new Animal();animals[1] = new Dog();animals[2] = new Cat();for(int i = 0; i < 3; i++) {animals[i]->makeSound(); // 动态绑定,调用对应派生类的函数}// 释放内存for(int i = 0; i < 3; i++) {delete animals[i];}return 0;
}

输出:

Some generic animal sound
Woof!
Meow!

尽管在 DogCat 类中没有使用 virtual 关键字,但 makeSound() 函数仍然被视为虚函数,并且能够通过基类指针正确调用对应的派生类函数。

哪些函数不能声明为虚函数

1. 普通函数(非成员函数)

无法声明为虚函数的原因:普通函数只能被重载(overload),不能被重写(override)。虚函数的目的是实现运行时多态,而普通函数没有关联的对象,无法在运行时根据对象类型做出不同的行为。

示例

#include <iostream>
using namespace std;// 错误 - 普通函数不能被声明为虚函数
// virtual void globalFunction() { cout << "Global function" << endl; }// 正确 - 普通函数可以重载但不能是虚函数
void globalFunction() { cout << "Global function" << endl; }
void globalFunction(int x) { cout << "Overloaded global function: " << x << endl; }int main() {globalFunction();globalFunction(10);return 0;
}

如果尝试将普通函数声明为虚函数,编译器会报错,因为虚函数需要一个虚函数表,而虚函数表必须与对象实例关联。

2. 构造函数

无法声明为虚函数的原因:构造函数的作用是初始化对象,在构造函数被调用时,对象尚未完全创建,虚函数表也尚未设置完成。此外,从语义上讲,构造函数是为了明确初始化对象成员,而虚函数是为了在不完全了解细节的情况下处理对象。

示例

#include <iostream>
using namespace std;class Base {
public:// 错误 - 构造函数不能是虚函数// virtual Base() { cout << "Base constructor" << endl; }// 正确 - 普通构造函数Base() { cout << "Base constructor" << endl; }
};class Derived : public Base {
public:Derived() { cout << "Derived constructor" << endl; }
};int main() {Derived d; // 先调用Base构造函数,再调用Derived构造函数return 0;
}

输出:

Base constructor
Derived constructor

构造函数的调用顺序是由继承关系决定的,从基类到派生类,这与虚函数的动态绑定机制不兼容。

3. 内联成员函数

无法声明为虚函数的原因:内联函数的目的是在编译时直接展开代码,减少函数调用开销,而虚函数是在运行时动态绑定的,这两个概念在实现上存在冲突。

示例

#include <iostream>
using namespace std;class Base {
public:// 声明为虚函数的内联函数 - 编译器会忽略inline关键字virtual inline void show() { cout << "Base show" << endl; }
};class Derived : public Base {
public:inline void show() override { cout << "Derived show" << endl; }
};int main() {Base* ptr = new Derived();ptr->show(); // 调用Derived::show(),内联特性被忽略delete ptr;return 0;
}

输出:

Derived show

在实际编译中,如果一个函数同时被声明为virtualinline,编译器会忽略inline特性,优先考虑虚函数的动态绑定特性。所以技术上可以同时使用这两个关键字,但实际上内联特性不会生效。

4. 静态成员函数

无法声明为虚函数的原因:静态成员函数属于类而非对象,所有对象共享同一份代码。虚函数通过对象的虚函数表实现动态绑定,而静态成员函数没有this指针,无法访问虚函数表。

示例

#include <iostream>
using namespace std;class Base {
public:// 错误 - 静态成员函数不能是虚函数// static virtual void staticFunction() { cout << "Base static function" << endl; }// 正确 - 普通静态成员函数static void staticFunction() { cout << "Base static function" << endl; }
};class Derived : public Base {
public:// 这是一个独立的静态函数,不是重写static void staticFunction() { cout << "Derived static function" << endl; }
};int main() {Base::staticFunction();    // 调用Base的静态函数Derived::staticFunction(); // 调用Derived的静态函数Base* ptr = new Derived();// 通过指针调用静态函数,实际上调用的是指针类型对应的类的静态函数ptr->staticFunction();     // 调用Base的静态函数delete ptr;return 0;
}

输出:

Base static function
Derived static function
Base static function

静态成员函数的调用在编译时就已确定,不会发生运行时的动态绑定。

5. 友元函数

无法声明为虚函数的原因:友元函数不是类的成员函数,而是被授予访问类的私有成员的外部函数。由于友元关系不能被继承,友元函数没有重写的概念,因此无法声明为虚函数。

示例

#include <iostream>
using namespace std;class Base {
private:int value = 10;// 错误 - 友元函数不能是虚函数// virtual friend void friendFunction(Base& obj) { cout << "Value: " << obj.value << endl; }// 正确 - 普通友元函数friend void friendFunction(Base& obj);
};void friendFunction(Base& obj) {cout << "Base value: " << obj.value << endl;
}class Derived : public Base {
private:int derivedValue = 20;// 这是一个新的友元函数,不是重写friend void friendFunction(Derived& obj);
};void friendFunction(Derived& obj) {cout << "Derived value: " << obj.derivedValue << endl;// 也可以通过Base类的友元函数访问基类部分的私有成员friendFunction(static_cast<Base&>(obj));
}int main() {Base b;Derived d;friendFunction(b);  // 调用Base的友元函数friendFunction(d);  // 调用Derived的友元函数return 0;
}

输出:

Base value: 10
Derived value: 20
Base value: 10

友元函数的调用是在编译时确定的,基于参数的静态类型,不会发生动态绑定。

总结

不能声明为虚函数的函数包括:

  1. 普通函数(非成员函数)- 缺少对象上下文
  2. 构造函数 - 对象尚未创建完成,无法动态绑定
  3. 内联成员函数 - 编译时展开与运行时绑定冲突(虽然可以同时使用关键字,但inline会被忽略)
  4. 静态成员函数 - 缺少this指针,无法访问虚函数表
  5. 友元函数 - 不是类的成员,无法继承也无法重写

纯虚函数和抽象类

纯虚函数是一种特殊的虚函数,它没有具体的实现,通常用于声明接口规范。其格式如下:

virtual 返回值类型 函数名(形参列表) = 0;
  • virtual 关键字表示这是一个虚函数。
  • = 0 表示这是一个纯虚函数,即没有具体的实现。

示例

以下是一个包含纯虚函数的基类和派生类的示例:

#include <iostream>
using namespace std;// 基类
class Base {
public:virtual void Print() = 0; // 纯虚函数
};// 派生类1
class Derived1 : public Base {
public:void Print() override { // 实现纯虚函数cout << "This is Class Derived1!" << endl;}
};// 派生类2
class Derived2 : public Base {
public:void Print() override { // 实现纯虚函数cout << "This is Class Derived2!" << endl;}
};int main() {Derived1 Cderived1;Derived2 Cderived2;Cderived1.Print(); // 调用派生类1的PrintCderived2.Print(); // 调用派生类2的Printcout << "---------------" << endl;Base *p1 = &Cderived1;Base *p2 = &Cderived2;p1->Print(); // 调用派生类1的Printp2->Print(); // 调用派生类2的Printreturn 0;
}

输出结果

This is Class Derived1!
This is Class Derived2!
---------------
This is Class Derived1!
This is Class Derived2!

作用

  1. 定义接口规范:纯虚函数主要用于定义接口规范,而将具体的实现留给派生类。它确保所有派生类都必须实现该函数,从而保证了多态的实现。
  2. 实现多态:通过纯虚函数,可以实现多态。在运行时,根据对象的实际类型调用对应的函数实现。
  3. 抽象类:包含纯虚函数的类称为抽象类。抽象类不能生成对象,但可以作为接口类,用于统一管理派生类对象。

使用场景

  • 抽象类:当基类中无法提供一个通用的实现,或者某些功能必须由派生类具体实现时,可以将函数定义为纯虚函数。
  • 多态:通过纯虚函数实现多态,可以在运行时根据对象的实际类型调用对应的函数实现。

注意事项

  1. 抽象类不能实例化:包含纯虚函数的类称为抽象类,抽象类不能生成对象。
  2. 派生类必须实现纯虚函数:如果派生类没有实现基类中的纯虚函数,则派生类也是抽象类,无法实例化。
  3. 纯虚函数不能被调用:纯虚函数没有具体的实现,因此不能直接调用。

示例代码解释

在上述代码中:

  • Base 类中的 Print 函数是一个纯虚函数,它没有具体的实现。
  • Derived1Derived2Base 的派生类,它们分别实现了 Print 函数。
  • main 函数中,通过基类指针调用派生类的 Print 函数,实现了多态。
http://www.dtcms.com/a/552405.html

相关文章:

  • wordpress获取小工具网站排名优化怎么样
  • 免费自助建站哪个平台好什么类型的网站容易被百度抓取
  • 网站空间ftp下载慢快速开发平台有哪些
  • 怎么做网站首页关键词电商代运营公司排行榜
  • 徐州市网站开发设计灵感网站整理
  • wordpress在页面中调用文章杭州新站整站seo
  • 手表网站登录页背景图优质的菏泽网站建设
  • 电商网站开发多少钱免费网站推广产品
  • 如何制作自己的网站国内做企业英文网站用什么cms
  • 网络公司网站建设报价软件设计专业介绍
  • 门户网站建设目的关注江苏建设厅网站
  • php建设网站所用开发软件凡科app制作
  • 公司注销 网站备案申请表seo建站教学
  • 专业的网站建设托管公司简介网页模板
  • 网站推广渠道类型外网wordpress好慢
  • 做国外网站的公证要多少钱wordpress php5.3.5访问慢
  • 江苏建设通网站做高端品牌网站
  • 深圳市招聘网站三合一网站建设官网
  • 苏州网站建设空间网页开发语言有哪几种
  • 四川省建设厅职称查询网站烟台网站建设外贸
  • 云南固恒建设集团有限公司网站女生读电子商务好就业吗
  • 小型公司建网站沈阳大东区做网站公司
  • 网站建设 中企动力中山wordpress模板下载云落
  • 烟台企业做网站甘肃网站建设哪家好
  • 苏州 网站 建设 公司事业单位可以建设网站吗
  • wordpress博客网站长沙网站建设建
  • 旅游网站开发公司济南网站建设 刘彬彬
  • 响应式网站psd尺寸青岛公司建站
  • 中交上航建设网站英文外链seo兼职
  • 成都大型网站设计公司做网站不搭建本地环境