C++默认构造函数详解
作者:Yolo_TvT
本文详细解析了C++中默认成员函数的概念,包括默认构造函数的作用与生成规则,并探讨了何时需要自定义默认构造函数及其应用场景,感兴趣的朋友一起看看吧
一、类的默认成员函数
- 当你定义一个空类时,编译器并不会真的“空手而归”。它会自动为你生成6个(C++98)或更多(C++11后)特殊的成员函数。这些函数被称为默认成员函数。
- 他们分别是:
| 函数 | 作用 |
|---|---|
| 默认构造函数 | 初始化对象 |
| 析构函数 | 清理对象资源 |
| 拷贝构造函数 | 用已有对象初始化新对象 |
| 赋值运算符重载 | 将已有对象赋值给另一对象 |
| 移动构造函数(C++11) | 用临时对象“转移”资源 |
| 移动赋值运算符(C++11) | 临时对象赋值 |
- 如果没有主动声明这些函数,编译器就会自动生成一个默认版本,即为默认成员函数。
二、构造函数的基本概念
- 构造函数是类中一种特殊的成员函数,它在对象创建时自动调用,用于初始化对象的成员变量。
构造函数的规则:
- 函数名与类名完全相同
- 没有返回值
- 可以重载(可以有多个参数不同的构造函数)
- 对象创建时自动执行
三、默认构造函数的含义
- 默认构造函数是指可以无实参可调用的构造函数。它包括两种情况:
- 程序员定义的默认构造函数:
- 程序员定义的无参构造函数。
- 程序员定义的全缺省参数的构造函数。
- 程序员没有定义构造函数,编译器自动生成的隐式默认构造函数。
- 程序员定义的默认构造函数:
class Student {
public:
// 无参构造函数
Student() {
name = "无名";
age = 0;
}
private:
string name;
int age;
};
cpp
class Point {
public:
// 全缺省参数的构造函数(也是默认构造函数)
Point(int x = 0, int y = 0) : x(x), y(y) {}
private:
int x, y;
};四、编译器自动生成的默认构造函数
- 若程序员没有实现构造函数,编译器会为你生成一个隐式默认构造函数。
class Dog {
string name;
int age;
// 编译器自动生成 Dog() {}
};
这个隐式构造函数会做什么?
- 对于内置类型(int, char, 指针等):不做任何初始化(不同编译器效果不同)。
- 对于自定义类型成员:调用它们各自的默认构造函数。
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A的构造函数" << endl; }
};
class B {
int x; // 内置类型,不会初始化(垃圾值)
A a; // 类类型,会调用A的默认构造函数
};
int main() {
B b; // 输出:A的构造函数(x保持随机)
}一旦你实现了构造函数,编译器就不再生成默认构造函数
class Student {
public:
Student(string n) { name = n; } // 自定义构造函数
private:
string name;
};
int main() {
Student s1("张三"); // 正确
// Student s2; // 错误!没有默认构造函数可用
}如果你既需要带参构造,又需要无参构造,需要手动提供默认构造函数。
五、默认构造函数的用途
1. 定义对象而不初始化
class Array {
int* data;
public:
Array() { data = nullptr; } // 允许定义空数组对象
};
Array arr; // 调用默认构造
2. 作为容器元素的默认构造要求
STL容器(如vector)在扩容或创建元素时,经常需要元素的默认构造函数。
vector<Student> v(10); // 需要Student有默认构造函数
3. 继承体系中基类的初始化
派生类构造函数会自动调用基类的默认构造函数(如果基类没有默认构造,派生类必须显式调用基类的带参构造)。
六、什么时候需要自定义默认构造函数?
| 情况 | 是否需要 |
|---|---|
| 类没有指针成员,且成员都有合理的默认值 | 不需要,编译器生成即可 |
| 成员中需要分配资源 | 需要(在构造中分配并初始化) |
| 需要给成员变量设置特定的初始值 | 需要 |
| 类有自定义的带参构造,但仍需无参创建对象 | 需要 |
class MyString {
char* buf;
public:
// 自定义默认构造:给指针一个安全的初始值
MyString() {
buf = new char[1];
buf[0] = '\0';
}
};七、C++11 的改进:default 和 delete
C++11允许你显式要求编译器生成默认版本,或禁止某个构造函数。
class Widget {
public:
Widget() = default; // 手动要求编译器生成默认构造
Widget(const Widget&) = delete; // 禁止拷贝构造
};
八、一个完整的例子
#include <iostream>
#include <string>
using namespace std;
class Book {
public:
// 默认构造函数
Book() {
title = "未命名";
price = 0.0;
cout << "调用默认构造函数" << endl;
}
// 带参构造函数(不是默认构造)
Book(string t, double p) : title(t), price(p) {
cout << "调用带参构造函数" << endl;
}
void print() {
cout << "书名:" << title << ",价格:" << price << endl;
}
private:
string title;
double price;
};
int main() {
Book b1; // 调用默认构造
Book b2("C++教程", 59.9); // 调用带参构造
b1.print();
b2.print();
return 0;
}
输出:
text
调用默认构造函数
调用带参构造函数
书名:未命名,价格:0
书名:C++教程,价格:59.9到此这篇关于C++:默认构造函数的文章就介绍到这了,更多相关C++:默认构造函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
