跳转到内容

C++ 构造函数

来自代码酷

C++构造函数[编辑 | 编辑源代码]

构造函数(Constructor)是C++面向对象编程中的核心概念之一,它是一种特殊的成员函数,用于在创建对象时初始化对象的成员变量。构造函数的名字与类名相同,没有返回类型(包括void),并且在对象创建时自动调用。

基本语法[编辑 | 编辑源代码]

构造函数的声明和定义方式如下:

class MyClass {
public:
    // 构造函数声明
    MyClass(); 
};

// 构造函数定义
MyClass::MyClass() {
    // 初始化代码
}

构造函数的类型[编辑 | 编辑源代码]

C++支持多种类型的构造函数,每种类型适用于不同的场景。

默认构造函数[编辑 | 编辑源代码]

默认构造函数(Default Constructor)是不带任何参数的构造函数。如果用户没有定义任何构造函数,编译器会自动生成一个默认构造函数。

class Box {
public:
    Box() { // 默认构造函数
        length = 0;
        width = 0;
        height = 0;
    }
private:
    double length;
    double width;
    double height;
};

参数化构造函数[编辑 | 编辑源代码]

参数化构造函数(Parameterized Constructor)允许在创建对象时传递参数来初始化成员变量。

class Box {
public:
    Box(double l, double w, double h) { // 参数化构造函数
        length = l;
        width = w;
        height = h;
    }
private:
    double length;
    double width;
    double height;
};

// 使用示例
Box myBox(10.0, 5.0, 2.0); // 创建对象并初始化

拷贝构造函数[编辑 | 编辑源代码]

拷贝构造函数(Copy Constructor)用于通过另一个同类对象初始化新对象。其形式为ClassName(const ClassName &obj)

class Box {
public:
    Box(const Box &other) { // 拷贝构造函数
        length = other.length;
        width = other.width;
        height = other.height;
    }
private:
    double length;
    double width;
    double height;
};

// 使用示例
Box box1(10.0, 5.0, 2.0);
Box box2 = box1; // 调用拷贝构造函数

构造函数的重载[编辑 | 编辑源代码]

C++允许构造函数重载,即一个类可以有多个构造函数,只要它们的参数列表不同。

class Box {
public:
    Box() { // 默认构造函数
        length = width = height = 0;
    }
    
    Box(double side) { // 立方体构造函数
        length = width = height = side;
    }
    
    Box(double l, double w, double h) { // 一般长方体构造函数
        length = l;
        width = w;
        height = h;
    }
private:
    double length;
    double width;
    double height;
};

// 使用示例
Box defaultBox;       // 调用默认构造函数
Box cube(5.0);        // 调用立方体构造函数
Box rectangle(10,5,2); // 调用长方体构造函数

初始化列表[编辑 | 编辑源代码]

C++提供了成员初始化列表(Member Initializer List)语法,可以更高效地初始化成员变量。

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

初始化列表比在构造函数体内赋值效率更高,特别是对于const成员和引用成员,必须使用初始化列表。

委托构造函数[编辑 | 编辑源代码]

C++11引入了委托构造函数(Delegating Constructor),允许一个构造函数调用同类中的另一个构造函数。

class Box {
public:
    Box() : Box(0, 0, 0) {} // 委托给三参数构造函数
    
    Box(double side) : Box(side, side, side) {} // 委托给三参数构造函数
    
    Box(double l, double w, double h) { // 主构造函数
        length = l;
        width = w;
        height = h;
    }
private:
    double length;
    double width;
    double height;
};

构造函数与继承[编辑 | 编辑源代码]

在继承体系中,派生类的构造函数需要负责基类子对象的初始化。

class Base {
public:
    Base(int value) : baseValue(value) {}
private:
    int baseValue;
};

class Derived : public Base {
public:
    Derived(int baseVal, int derivedVal) 
        : Base(baseVal), derivedValue(derivedVal) {}
private:
    int derivedValue;
};

实际应用案例[编辑 | 编辑源代码]

考虑一个银行账户系统的简单实现:

class BankAccount {
public:
    BankAccount(std::string owner, double initialBalance)
        : owner_(owner), balance_(initialBalance) {
        std::cout << "Account created for " << owner_ 
                  << " with balance " << balance_ << std::endl;
    }
    
    void deposit(double amount) {
        balance_ += amount;
    }
    
    void withdraw(double amount) {
        if (amount <= balance_) {
            balance_ -= amount;
        } else {
            std::cout << "Insufficient funds!" << std::endl;
        }
    }
    
    void display() const {
        std::cout << owner_ << "'s balance: " << balance_ << std::endl;
    }

private:
    std::string owner_;
    double balance_;
};

// 使用示例
int main() {
    BankAccount account("John Doe", 1000.0);
    account.deposit(500.0);
    account.withdraw(200.0);
    account.display();
    return 0;
}

输出:

Account created for John Doe with balance 1000
John Doe's balance: 1300

常见问题与注意事项[编辑 | 编辑源代码]

1. 隐式转换:单参数构造函数可能导致意外的隐式类型转换,可以使用explicit关键字防止。 2. 虚构造函数:构造函数不能是虚函数。 3. 纯虚构造函数:构造函数不能是纯虚函数。 4. 构造顺序:成员变量按照声明顺序初始化,而非初始化列表中的顺序。 5. 异常处理:构造函数可以抛出异常,但需要妥善处理资源分配。

总结[编辑 | 编辑源代码]

构造函数是C++类的重要组成部分,它:

  • 与类同名
  • 没有返回类型
  • 在对象创建时自动调用
  • 可以有多种形式(默认、参数化、拷贝等)
  • 可以使用初始化列表提高效率
  • 在继承体系中需要特别注意基类初始化

理解并正确使用构造函数是掌握C++面向对象编程的关键一步。