前言
这个栏目是为了速成C++机考准备的,以题目为导向。
主要是通过ChatGPT给出的题目与测试用例来写。
题目
题目 1:抽象类和纯虚函数
题目:定义一个抽象类 Shape,该类有一个纯虚函数 area(),返回形状的面积。然后定义两个派生类Circle 和 Rectangle,分别实现 area() 函数。
要求: 抽象类 Shape 必须包含一个纯虚函数 area() 派生类 Circle 需要一个成员变量表示半径,并实现 area()
计算圆的面积 派生类 Rectangle 需要两个成员变量表示长和宽,并实现 area() 计算矩形的面积
#include<iostream>
#include<cmath>
#include<vector>
class Shape {
public:
virtual double area() const = 0;
virtual ~Shape() {}
};
class Circle : public Shape {
double radius;
public:
Circle(double r) : radius(r) {}
double area() const override {
return M_PI * radius * radius;
}
};
class Rectangle : public Shape {
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double area() const override {
return width * height;
}
};
int main() {
std::vector<Shape*> shapes;
shapes.push_back(new Circle(5));
shapes.push_back(new Rectangle(4, 6));
for (Shape* shape : shapes) {
std::cout << "Area: " << shape->area() << std::endl;
}
for (Shape* shape : shapes) {
delete shape;
}
return 0;
}
相关概念
抽象类
定义:抽象类是不能被实例化的类,它主要用作其他类的基类。抽象类通常包含至少一个纯虚函数,表示它们定义了一些公共接口,但是这些接口必须由派生类来实现。
用途:用于为派生类提供公共接口,确保派生类实现某些功能。
纯虚函数
定义:纯虚函数是一种特殊的虚函数,它在基类中没有实现,只是在声明时被赋予‘=0’.它强制派生类必须是实现该函数。
用途:用于定义接口,确保派生类提供具体实现。
class AbstractClass {
public:
virtual void pureVirtualFunction() = 0; // 纯虚函数
};
虚函数
定义:虚函数是在基类中使用关键字virtual声明的函数,虚函数允许在派生类中重写它。
作用途:虚函数实现了动态多态性,即在运行时根据对象类型调用相关的函数。
class Base {
public:
virtual void display() {
std::cout << "Display from Base" << std::endl;
}
};
class Derived : public Base {
public:
void display() override {
std::cout << "Display from Derived" << std::endl;
}
};
}
动态多态性
定义:动态多态性是指在程序运行时,通过基类指针或应用调用派生类的重写函数。
用途:可以编写更加灵活和可拓展的代码。
Base* b = new Derived();
b->display(); // 输出: Display from Derived
delete b;
基类
定义:基类是一个可以被其他类继承的类。它包含其他类可以使用或重写的成员函数和成员变量。
用途:基类用于提供共享的接口和实现,以便多个派生类可以复用这些功能。
class Base {
public:
void commonFunction() {
// 基类中的方法
}
};
派生类
定义:派生类是从基类继承的类。它可以重用基类的成员,并且可以添加新的成员或重写基类的成员。
用途:派生类用于扩展或修改基类的功能。
class Derived : public Base {
public:
void additionalFunction() {
// 派生类中的新方法
}
};
接口
定义:通常指的是包含纯虚函数的抽象类,接口有定义了一组功能,但是不提供具体实现。
用途:用以定义类必须实现的一组功能,而不关心具体的实现细节。
class Interface {
public:
virtual void function() = 0; // 纯虚函数
};
公共接口
定义:是指一个类向外部暴露(public)的一组成员函数,这些函数定义了该类的功能。
用途:公共接口用于与其他类或代码模块进行交互。
class MyClass {
public:
void publicFunction() {
// 公共接口方法
}
};
重写 override
定义:在派生类中重新定义基类的虚函数。重写的函数在运行时会根据对象的实际类型被调用。
用途:重写用于改变或拓展基类的行为。
class Base {
public:
virtual void virtualFunction() {
// 基类的虚函数
}
};
class Derived : public Base {
public:
void virtualFunction() override {
// 派生类重写的虚函数
}
};
多态
定义:多态是面向对象编程的一个特性,允许你通过基类指针或引用调用派生类的重写函数。多态性使得同一个函数调用可以表现出不同的行为。
用途:编写灵活和可拓展的方法。
Base* basePtr = new Derived();
basePtr->virtualFunction(); // 调用的是 Derived::virtualFunction
基类指针或引用
定义:基类指针或引用是指向基类对象的指针或引用。它们可以指向基类对象或派生类对象。
用途:基类指针或引用用于实现多态性,通过它们可以在运行时调用派生类的重写函数。
Base* basePtr = new Derived(); // 基类指针指向派生类对象
Base& baseRef = *basePtr; // 基类引用指向派生类对象
basePtr->virtualFunction(); // 调用派生类的重写函数
baseRef.virtualFunction(); // 调用派生类的重写函数
析构函数
定义:析构函数是一种特殊的成员函数,用于在对象生命周期结束时执行清理工作。它的名称是在类名前加上 ~ 符号。
析构函数在对象被销毁时自动调用,无需手动调用。析构函数不能有返回类型,也不能接受参数。
虚析构函数
定义:在基类中将析构函数声明为虚函数。虚析构函数确保即使通过基类指针删除对象,也能正确调用派生类的析构函数。
用途:虚析构函数用于在继承层次结构中正确释放资源。如果基类有虚函数,通常也需要一个虚析构函数,以便在删除基类指针指向的派生类对象时,能够正确地调用派生类的析构函数,释放派生类特有的资源。
初始化列表 vs 函数体内赋值
性能:初始化列表直接初始化成员变量,通常比在函数体内先调用默认构造函数再赋值更高效。对于内置类型,这种差异不明显,但对于复杂类型(如自定义类类型或容器类型),差异会比较显著。
常量成员:常量成员变量(const)和引用类型成员变量必须在初始化列表中初始化,不能在构造函数体内赋值。如果不使用初始化列表,这些成员变量无法正确初始化。
继承:在派生类的构造函数中,通过初始化列表可以显式调用基类的构造函数,确保基类部分先被正确初始化。
初始化列表
// 构造函数,使用初始化列表初始化成员变量 radius
Circle(double r) : radius(r) {
std::cout << "Circle constructed with radius: " << radius << std::endl;
}
函数体内赋值
// 构造函数,在函数体内初始化成员变量 radius
Circle(double r) {
radius = r; // 在构造函数体内赋值
std::cout << "Circle constructed with radius: " << radius << std::endl;
}