Skip to content

C++ OOP 面试高频知识点 - 03

构造函数(无参、有参、拷贝构造、移动构造、委托构造)

1. 构造函数的基本概念

构造函数(Constructor) 是在创建对象时自动调用的特殊成员函数,它用于初始化对象的成员变量。构造函数的名称必须与类名完全相同,且不能有返回类型(包括 void)。

class MyClass {
public:
    MyClass() {
        // 构造函数实现
        cout << "Constructor called!" << endl;
    }
};

2. 构造函数的类型

2.1 无参构造函数

无参构造函数是指没有参数的构造函数。如果类中没有定义任何构造函数,编译器会自动生成一个默认的无参构造函数。

class MyClass {
public:
    MyClass() {
        // 无参构造函数
        x = 0;
        y = 0;
    }

private:
    int x, y;
};

int main() {
    MyClass obj; // 调用无参构造函数
    return 0;
}

2.2 有参构造函数

有参构造函数可以接受参数,用于初始化对象的成员变量。

class Point {
public:
    Point(int x, int y) {
        this->x = x;
        this->y = y;
    }

private:
    int x, y;
};

int main() {
    Point p(10, 20); // 调用有参构造函数
    return 0;
}

2.3 拷贝构造函数

拷贝构造函数用于创建一个新对象,其初始值来自另一个已存在的对象。

class MyClass {
public:
    MyClass(const MyClass& other) {
        // 拷贝构造函数
        this->x = other.x;
        this->y = other.y;
    }

private:
    int x, y;
};

int main() {
    MyClass obj1(10, 20);
    MyClass obj2(obj1); // 调用拷贝构造函数
    return 0;
}

2.4 移动构造函数

移动构造函数用于将资源从一个对象转移到另一个对象,避免了不必要的拷贝。

class MyClass {
public:
    MyClass(MyClass&& other) noexcept {
        // 移动构造函数
        this->data = other.data;
        other.data = nullptr;
    }

private:
    int* data;
};

2.5 委托构造函数

委托构造函数允许一个构造函数调用另一个构造函数,避免了代码重复。

class MyClass {
public:
    MyClass() : MyClass(0, 0) { // 委托给有参构造函数
        cout << "Default constructor" << endl;
    }

    MyClass(int x, int y) {
        this->x = x;
        this->y = y;
        cout << "Parameterized constructor" << endl;
    }

private:
    int x, y;
};

3. 构造函数的特殊特性

3.1 默认构造函数

如果类中没有定义任何构造函数,编译器会自动生成一个默认构造函数。如果定义了其他构造函数,编译器不会自动生成默认构造函数。

class MyClass {
public:
    MyClass(int x) { // 定义了有参构造函数
        this->x = x;
    }

private:
    int x;
};

int main() {
    // MyClass obj; // 错误:无默认构造函数
    MyClass obj(10); // 正确
    return 0;
}

3.2 初始化列表

使用初始化列表可以更高效地初始化成员变量,避免了默认初始化和赋值操作。

class Point {
public:
    // 使用初始化列表
    Point(int x, int y) : x(x), y(y) {
        // 构造函数体
    }

private:
    int x, y;
};

3.3 explicit 关键字

使用 explicit 关键字可以防止隐式类型转换。

class MyClass {
public:
    explicit MyClass(int x) {
        this->x = x;
    }

private:
    int x;
};

int main() {
    MyClass obj = 10; // 错误:不能隐式转换
    MyClass obj(10); // 正确
    return 0;
}

4. 常见问题和回答

问题 1:构造函数为什么没有返回类型?

构造函数的目的是初始化对象,而不是返回值。如果有返回类型,会导致语法歧义。

问题 2:什么是拷贝构造函数?什么时候会被调用?

拷贝构造函数用于创建一个新对象,其初始值来自另一个已存在的对象。当对象作为参数传递、作为返回值返回或使用 = 初始化时会被调用。

问题 3:为什么需要移动构造函数?

移动构造函数可以避免不必要的拷贝操作,提高程序效率,特别是在处理大型对象时。


总结

构造函数是 C++ 类中非常重要的成员函数,它负责在创建对象时初始化成员变量。C++ 提供了多种类型的构造函数,包括无参、有参、拷贝、移动和委托构造函数,以满足不同的需求。


练习建议: 1. 设计一个 Date 类,包含年、月、日成员变量 2. 实现无参、有参、拷贝构造和移动构造函数 3. 使用初始化列表初始化成员变量