面试题答案
一键面试- 设计思路:
- 由于存在多态性和动态分配资源,不能使用默认的拷贝构造函数,因为默认拷贝构造函数进行的是浅拷贝,会导致多个对象共享同一份动态分配的资源,在析构时出现多次释放同一资源的错误。
- 为了确保资源的正确复制与管理,在基类
Shape
中,需要实现深拷贝构造函数。在深拷贝构造函数中,为新对象分配独立的资源,并将原对象资源的内容复制过来。 - 为了避免切片问题,需要在基类中定义虚的克隆函数(
clone
),每个派生类重写这个函数,返回自身的深拷贝。这样在进行对象拷贝时,可以通过调用clone
函数实现多态的深拷贝。
- 关键代码片段:
#include <iostream>
#include <memory>
// 资源类
class Resource {
public:
Resource() { std::cout << "Resource constructed" << std::endl; }
~Resource() { std::cout << "Resource destructed" << std::endl; }
};
// 基类 Shape
class Shape {
protected:
std::unique_ptr<Resource> res;
public:
Shape() : res(std::make_unique<Resource>()) {}
// 虚析构函数,确保派生类析构时调用正确的析构函数
virtual ~Shape() = default;
// 虚克隆函数
virtual std::unique_ptr<Shape> clone() const = 0;
// 深拷贝构造函数
Shape(const Shape& other) : res(std::make_unique<Resource>(*other.res)) {}
// 深拷贝赋值运算符重载
Shape& operator=(const Shape& other) {
if (this != &other) {
res = std::make_unique<Resource>(*other.res);
}
return *this;
}
};
// 派生类 Circle
class Circle : public Shape {
public:
Circle() = default;
// 重写克隆函数
std::unique_ptr<Shape> clone() const override {
return std::make_unique<Circle>(*this);
}
};
// 派生类 Rectangle
class Rectangle : public Shape {
public:
Rectangle() = default;
// 重写克隆函数
std::unique_ptr<Shape> clone() const override {
return std::make_unique<Rectangle>(*this);
}
};
在上述代码中:
Resource
类模拟动态分配的资源。Shape
类包含指向Resource
的std::unique_ptr
,实现了深拷贝构造函数和赋值运算符重载。同时定义了虚析构函数和纯虚的clone
函数。Circle
和Rectangle
派生类重写了clone
函数,返回自身类型的深拷贝。这样在进行多态对象拷贝时,可以通过clone
函数实现正确的深拷贝并避免切片问题。例如:
int main() {
std::unique_ptr<Shape> shape1 = std::make_unique<Circle>();
std::unique_ptr<Shape> shape2 = shape1->clone();
return 0;
}
这里 shape2
是 shape1
的深拷贝,且 shape2
的实际类型和 shape1
相同,避免了切片问题。