1、面向对象多态的思想
面向对象多态是面向对象编程中的一个重要概念,指的是同一种对象或行为的不同表现形式。通过多态,可以以统一的方式处理不同类型的对象,提高代码的灵活性和可扩展性。
使用多态的主要目的是增加代码的可复用性和可扩展性。通过将共同行为抽象成接口或基类,不同的子类可以实现自己独特的行为,但在使用时可以通过统一的接口进行操作,而不需要考虑具体的子类类型。这样可以使代码更加灵活,便于后续的扩展和维护。下面先举个简单的例子来说明,相关知识点稍后将要学习,读者先对其有个印象,先不必纠结不懂的知识点,最好亲自动手上机书写代码并调试。
示例:
下面是一个简单的关于电脑的例子,通过多态实现了不同类型的设备(键盘、鼠标、显示器)的连接和操作。
// 设备基类
class Device {
public:
virtual void connect() {
std::cout << “Device connected.” << std::endl;
}
virtual void operate() = 0; // 纯虚函数,需要在子类中实现
};
// 键盘类
class Keyboard : public Device {
public:
void connect() override {
std::cout << “Keyboard connected.” << std::endl;
}
void operate() override {
std::cout << “Typing…” << std::endl;
}
};
// 鼠标类
class Mouse : public Device {
public:
void connect() override {
std::cout << “Mouse connected.” << std::endl;
}
void operate() override {
std::cout << “Moving mouse…” << std::endl;
}
};
// 显示器类
class Monitor : public Device {
public:
void connect() override {
std::cout << “Monitor connected.” << std::endl;
}
void operate() override {
std::cout << “Displaying…” << std::endl;
}
};
// 主函数
int main() {
Device* devices[3]; // 设备数组
Keyboard keyboard;
Mouse mouse;
Monitor monitor;
devices[0] = &keyboard;
devices[1] = &mouse;
devices[2] = &monitor;
for (int i = 0; i < 3; i++) {
devices[i]->connect();
devices[i]->operate();
}
return 0;
}
在上述例子中,通过将设备抽象成基类Device,每个设备类型都继承自Device并实现自己的connect和operate方法。通过使用多态,在主函数中可以统一以Device指针的形式访问不同类型的设备,并调用相应的方法。这样就可以以统一的方式处理不同设备的连接和操作,提高了代码的可复用性和可扩展性。
2、虚函数
(1)为什么使用虚函数
C++中的虚函数是在基类中声明并在派生类中重写的成员函数。使用关键字`virtual`来声明一个虚函数。当使用基类指针或引用调用虚函数时,根据对象的实际类型,程序会动态地调用相应的派生类中的函数。
虚函数的使用有以下几个好处:
(1)实现运行时多态性:通过虚函数,可以在运行时选择正确的函数实现,而不是在编译时静态地绑定到基类函数。这样,可以根据对象的实际类型来调用相应的派生类函数,实现多态性。这是面向对象编程中的一个核心概念。
(2)通过基类指针或引用访问派生类的成员函数:使用基类指针或引用来访问派生类的成员函数,可以简化代码,并提高代码的可扩展性和灵活性。通过虚函数,可以以统一的方式操作不同类型的对象,而不需要根据对象的具体类型编写大量的条件语句。
(3)在继承关系中覆盖基类函数:派生类可以通过重写继承的虚函数来覆盖基类的实现。这使得派生类可以根据自身的需要来修改继承的行为,从而实现定制化和特殊化的功能。这是面向对象编程的继承和多态性的基本特性之一。
通过使用虚函数,可以实现动态的函数调用和多态性,使得程序更加灵活和可扩展。虚函数是C++中实现多态性的重要机制之一,它是面向对象编程的核心概念之一。
(2)虚函数的声明和定义
虚函数的声明和定义步骤如下:
【1】在基类中使用virtual关键字声明虚函数。
【2】在派生类中重写基类的虚函数。
以下是一个最简单的例子,演示了虚函数的声明和定义:
#include <iostream>
class Base {
public:
virtual void display() {
std::cout << “This is the Base class” << std::endl;
}
};
class Derived : public Base {
public:
void display() {
std::cout << “This is the Derived class” << std::endl;
}
};
int main() {
Base* basePtr;
Base baseObj;
Derived derivedObj;
basePtr = &baseObj;
basePtr->display(); // 调用 Base 类的 display 函数
basePtr = &derivedObj;
basePtr->display(); // 调用 Derived 类的 display 函数
return 0;
}
在这个例子中,我们定义了一个基类Base和一个派生类Derived。Base类中有一个虚函数display(),Derived类重写了这个虚函数。
在main()函数中,我们创建了一个基类指针basePtr并分别指向基类对象和派生类对象。通过使用基类指针调用`display()`函数,我们可以看到根据对象的实际类型,程序会动态地调用相应的派生类中的函数。
输出结果为:
“`
This is the Base class
This is the Derived class
“`
可以看到,通过虚函数的使用,程序根据对象的实际类型,动态地调用了正确的派生类中的函数实现。
(3)虚函数的访问
【1】对象名访问
class Base {
public:
virtual void display() {
cout << “This is the Base class” << endl;
}
};
class Child : public Base {
public:
void display() {
cout << “This is the child class” << endl;
}
};
int main() {
//创建基类的对象obj_base
Base obj_base;
//创建派生类的对象obj_child
Child obj_child;
//通过对象名调用虚函数
obj_base.display();
//通过对象名调用虚函数
obj_child.display();
//通过类名加作用域限定符指明要调用的方法
obj_base.Base::display();
//通过类名加作用域限定符指明要调用的方法
obj_child.Child::display();
return 0;
}
【2】基指针访问
基指针访问指的是使用基指针分别指向派生类的地址,然后调用虚函数,这里涉及基指针转换规则的问题,转换规则如下。
1)指向基类的指针,可以指向它的公有派生的对象,但不能指向私有派生的对象。
2)只能利用它直接访问派生类从基类继承来的成员,不能直接访问公有派生类中特定的成
3)不能将指向派生类对象的指针指向其基类的一个对象。
class Base {
public:
virtual void display() {
cout << “This is the Base class” << endl;
}
};
class Child : public Base {
public:
void display() {
cout << “This is the child class” << endl;
}
};
int main() {
//创建基类的对象obj_base;使用基类对象地址为基类指针赋值
Base obj_base;
Base* pBase = &obj_base;
//创建派生类的对象obj_child;使用派生类对象地址为派生类指针赋值
Child obj_child;
Child* pChild = &obj_child;
pBase->display();
pChild->display();
//将派生类指针赋值给基类指针
pBase = pChild;
pBase->display();
//使用基类对象地址为派生类指针赋值
pChild = (Child*)&obj_base;
pChild->display();
pChild->Base::display();
return 0;
}
【3】引用访问
使用引用访问虚函数与使用指针访问虚函数类似,不同的是引用已经声明,不能修改,因此在使用上有一定限制,但这在一定程度上提高了代码的安全性,特别是在函数参数传递等场合中,可以将引用理解成一种“受限制的指针”,如下列代码所示。
class Base {
public:
virtual void display() {
cout << “This is the Base class” << endl;
}
};
class Child : public Base {
public:
void display() {
cout << “This is the child class” << endl;
}
};
int main() {
//创建基类的对象obj_base
Base obj_base;
//创建派生类的对象obj_child
Child obj_child;
//声明基类的引用,用基类对象初始化
Base& rBase1 = obj_base;
rBase1.display();
//声明基类的引用,用派生类对象初始化
Base& rBase2 = obj_child;
rBase2.display();
return 0;
}
【4】类内访问
在类内的成员函数中访问该类层次中的虚函数,要使用this指针,如下所示。
class Base {
public:
virtual void display() {
cout << “This is the Base class” << endl;
}
//使用this或者直接访问
void call_base_1(){
this->display();
}
void call_base_2(){
Base::display();
}
};
class Child : public Base {
public:
//对虚函数进行覆盖
void display() {
cout << “This is the child class” << endl;
}
void call_child_1(){
display();
}
};
int main() {
Base obj_base;
Child obj_child;
obj_base.call_base_1();
obj_child.call_child_1();
Base* pBase = &obj_base;
pBase->call_base_1();
pBase->call_base_2();
pBase = &obj_child;
pBase->call_base_1();
pBase->call_base_2();
return 0;
}
3、纯虚函数
C++中的纯虚函数是在基类中声明但没有提供实现的虚函数。纯虚函数通过使用“= 0”来声明。由于纯虚函数没有具体的实现,所以不能直接创建基类的对象,而只能在派生类中提供具体的实现。纯虚函数一般定义形式如下所示:
class 类名{
virtual 类型 函数名(参数表) = 0;
…
}
以下是一个关于电脑的例子,演示了纯虚函数的声明和使用:
#include <iostream>
class Computer {
public:
virtual void turnOn() = 0; // 纯虚函数,没有具体实现
virtual void turnOff() = 0; // 纯虚函数,没有具体实现
};
class Desktop : public Computer {
public:
void turnOn() override {
cout << “Desktop is turning on…” << endl;
}
void turnOff() override {
cout << “Desktop is turning off…” << endl;
}
};
class Laptop : public Computer {
public:
void turnOn() override {
cout << “Laptop is turning on…” << endl;
}
void turnOff() override {
cout << “Laptop is turning off…” << endl;
}
};
int main() {
Computer* computer;
Desktop desktop;
Laptop laptop;
computer = &desktop;
computer->turnOn(); // 调用 Desktop 类的 turnOn 函数
computer->turnOff(); // 调用 Desktop 类的 turnOff 函数
computer = &laptop;
computer->turnOn(); // 调用 Laptop 类的 turnOn 函数
computer->turnOff(); // 调用 Laptop 类的 turnOff 函数
return 0;
}
在这个例子中,我们定义了一个基类Computer和两个派生类Desktop和Laptop。Computer类中声明了两个纯虚函数turnOn()和turnOff(),并没有提供具体的实现。派生类Desktop和Laptop分别重写了这两个纯虚函数,提供了具体的实现。
在main()函数中,我们创建了一个基类指针computer并分别指向派生类对象desktop和laptop。通过使用基类指针调用turnOn()和turnOff()函数,我们可以看到根据对象的实际类型,程序会动态地调用相应的派生类中的函数实现。
输出结果为:
Desktop is turning on…
Desktop is turning off…
Laptop is turning on…
Laptop is turning off…
可以看到,通过纯虚函数的使用,我们可以在基类中声明接口,而将具体的实现推迟到派生类中。纯虚函数在面向对象设计中具有重要的作用,可以实现接口和抽象类的概念,并通过派生类提供具体的实现。


















暂无评论内容