📅  最后修改于: 2023-12-03 14:39:54.796000             🧑  作者: Mango
在 C++ 中,构造函数是一个特殊的函数,用于创建对象时初始化对象的数据成员。在某些情况下,构造函数可以调用覆盖(override)方法来实现更复杂的初始化逻辑。本文将介绍 C++ 的构造函数和覆盖方法的基本概念,并给出相关的代码示例。
构造函数与类的名称相同,没有返回类型,可以有参数。构造函数在对象创建时被调用。如果没有定义构造函数,则编译器会生成一个默认的构造函数。
构造函数的主要作用是为数据成员赋值以及执行其他必要的初始化操作。可以通过初始化列表或构造函数体中的代码来初始化数据成员。
下面是一个简单的示例,展示了如何在构造函数中初始化数据成员:
class Point {
public:
Point(int x, int y): m_x(x), m_y(y) {}
private:
int m_x;
int m_y;
};
在上面的示例代码中,构造函数 Point
接受两个参数 x
和 y
,使用初始化列表初始化对象的数据成员 m_x
和 m_y
。
在 C++ 中,覆盖(override)是指在派生类中重新定义(或实现)基类的虚函数。如果派生类中定义了一个与基类中的虚函数名称、返回类型和参数列表相同的函数,则该函数将覆盖基类的虚函数。
覆盖的主要目的是实现多态性。如果将一个基类指针指向一个派生类对象,然后调用虚函数,将调用派生类中的版本,而不是基类中的版本。
下面是一个简单的示例,展示了如何在派生类中覆盖一个基类的虚函数:
class Shape {
public:
virtual void draw() const {
std::cout << "Shape::draw()" << std::endl;
}
};
class Circle : public Shape {
public:
void draw() const override {
std::cout << "Circle::draw()" << std::endl;
}
};
在上面的示例中,类 Shape
定义了一个虚函数 draw
,派生类 Circle
重新定义了该函数,并使用关键字 override
声明它是对基类函数的覆盖。
在某些情况下,构造函数可以调用覆盖(override)方法来实现更复杂的初始化逻辑。这是因为,在构造函数中调用虚函数时,将调用正在构造的对象类型的函数版本,而不是派生类的版本。这意味着,即使在派生类中已经覆盖了基类的虚函数,构造函数也可以通过调用基类的虚函数来执行一些预处理或其他初始化操作。
下面是一个简单的示例,展示了如何在构造函数中调用覆盖方法:
class Shape {
public:
Shape(int x, int y): m_x(x), m_y(y) {
draw();
}
virtual void draw() const {
std::cout << "Shape::draw() x=" << m_x
<< " y=" << m_y << std::endl;
}
private:
int m_x;
int m_y;
};
class Circle : public Shape {
public:
Circle(int x, int y, int r): Shape(x, y), m_r(r) {}
void draw() const override {
std::cout << "Circle::draw() x=" << m_x
<< " y=" << m_y << " r=" << m_r << std::endl;
}
private:
int m_r;
};
在上面的示例中,类 Shape
定义了一个构造函数 Shape
,并在构造函数中调用虚函数 draw
。派生类 Circle
定义了一个构造函数 Circle
,在其中调用基类的构造函数,并初始化自己的数据成员。同时,Circle
重新定义了虚函数 draw
,并使用关键字 override
声明。
当创建一个 Circle
对象时,将首先调用 Shape
的构造函数,在其中调用了虚函数 Shape::draw()
。此时,Circle
对象还没有完全构造完毕,它的数据成员 m_r
还没有被初始化。然而,由于虚函数的多态性,此时调用的是 Shape::draw()
而不是 Circle::draw()
。
接下来,返回执行派生类 Circle
的构造函数,其中完成了对数据成员 m_r
的初始化。此时,对象已经完全构造完毕,可以调用虚函数 draw
来绘制圆形。此时,调用的将是派生类 Circle
的版本,因为 Circle
已经完全构造好了。
本文介绍了 C++ 的构造函数和覆盖方法的基本概念,并给出了相关的代码示例。在某些情况下,构造函数可以调用覆盖方法来实现更复杂的初始化逻辑。当调用虚函数时,将调用正在构造的对象类型的函数版本,而不是派生类的版本。这使得构造函数可以在对象完全构造之前执行一些必要的预处理操作。