类的成员函数
在C++中,类的成员函数是定义在类内部的函数,用于描述类对象的行为或操作。它们可以通过对象或类的实例来调用。成员函数分为几类,包括普通成员函数、构造函数、析构函数、静态成员函数、常量成员函数等。
1. 成员函数的定义方式
- 在类内定义:定义直接放在类体内,通常是小型函数
- 在类外定义:定义放在类体之外,需要使用作用域解析运算符
::
来指定函数所属的类
2. 成员函数的访问权限
根据关键字 public
、protected
、private
,成员函数的访问权限分为以下三种:
public
:可以从类外通过对象访问。protected
:只能在类内或派生类中访问。private
:仅在类内访问。
3. 普通成员函数
普通成员函数是定义在类内部的函数,用于描述类对象的行为或操作。它们可以通过对象或类的实例来调用。
4. 常成员函数
- 不允许修改成员变量
- 在函数声明后加
const
关键字。
1 | class MyClass { |
5. 静态成员函数
- 使用
static
关键字声明。 - 不依赖于对象,只能访问静态成员变量。
1 | class MyClass { |
6. 构造函数
构造函数是一种特殊的成员函数,用于初始化对象。它的名字与类名相同,并且没有返回值(连 void 都不能写)。构造函数的主要作用是在创建对象时自动执行初始化操作。
构造函数可以重载,即可以定义多个构造函数,每个构造函数的参数列表不同。当创建对象时,根据传递的参数列表选择合适的构造函数来初始化对象。
6.1. 默认构造函数
不带参数或参数都有默认值的构造函数。
6.2. 带参数的构造函数
带参数的构造函数可以在创建对象时传递参数,用于初始化对象的成员变量。
6.3. 拷贝构造函数
拷贝构造函数是一种特殊的构造函数,用于创建一个新对象,并将另一个对象的值复制到新对象中。它的参数是一个同类对象的引用。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28class MyClass {
public:
int value;
MyClass() { // 默认构造函数
std::cout << "默认构造函数被调用!" << std::endl;
}
MyClass(int v) { // 带参数的构造函数
value = v;
std::cout << "带参数构造函数被调用,value = " << value << std::endl;
}
/*MyClass(int v) : value(v) { // 另一种带参数的构造函数写法
std::cout << "带参数构造函数被调用,value = " << value << std::endl;
}*/
MyClass(const MyClass& obj) { // 拷贝构造函数
value = obj.value;
std::cout << "拷贝构造函数被调用!" << std::endl;
}
};
int main() {
MyClass obj1; // 调用默认构造函数
MyClass obj2(10); // 调用带参数的构造函数
MyClass obj3 = obj2; // 调用拷贝构造函数
return 0;
}
6.4. 委托构造函数(C++11 引入)
委托构造函数是一种特殊的构造函数,它可以在一个构造函数中调用另一个构造函数来初始化对象。这样可以减少代码重复,提高代码的可维护性。1
2
3
4
5
6
7
8
9
10
11
12class MyClass {
public:
MyClass() : MyClass(0) {} // 委托到另一个构造函数
MyClass(int x) {
std::cout << "x = " << x << std::endl;
}
};
int main() {
MyClass obj; // 调用默认构造函数,实际委托到 MyClass(int x)
return 0;
}
6.5. 显式构造函数(explicit)
防止隐式类型转换。1
2
3
4
5
6
7
8
9
10
11
12class MyClass {
public:
explicit MyClass(int x) {
std::cout << "显式构造函数被调用,x = " << x << std::endl;
}
};
int main() {
MyClass obj1(10); // OK,显式调用
// MyClass obj2 = 20; // 错误,禁止隐式转换
return 0;
}
6.6. 构造函数与初始化列表
使用初始化列表可以更高效地初始化成员变量,尤其是常量或引用成员。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class MyClass {
int a;
const int b;
int& c;
public:
MyClass(int x, int y, int& z) : a(x), b(y), c(z) { // 初始化列表,这是一个带参数的构造函数
std::cout << "初始化列表构造函数被调用" << std::endl;
}
};
int main() {
int val = 10;
MyClass obj(1, 2, val);
return 0;
}
7. 析构函数
析构函数是一种特殊的成员函数,用于在对象销毁时执行清理操作。它的名字与类名相同,前面加上一个波浪号~
,并且没有返回值(连 void 都不能写)。析构函数的主要作用是在对象销毁时自动执行清理操作,例如释放动态分配的内存、关闭文件等。
析构函数只能有一个,不能重载。当对象超出作用域或显式调用 delete 操作符时,会自动调用析构函数。1
2
3
4
5
6
7
8
9
10
11
12class MyClass {
public:
~MyClass() { // 析构函数
std::cout << "析构函数被调用,清理资源!" << std::endl;
}
};
int main() {
MyClass obj; // 创建对象时调用构造函数
// 离开作用域时自动调用析构函数
return 0;
}
8. 虚函数
虚函数是一种特殊的成员函数,用于实现多态性。在基类中声明虚函数时,需要在函数声明前加上 virtual
关键字。在派生类中重写虚函数时,不需要使用 virtual
关键字,但必须与基类中的虚函数具有相同的函数签名(即函数名、参数列表和返回类型)。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class Base {
public:
virtual void show() {
std::cout << "基类 show 函数" << std::endl;
}
};
class Derived : public Base {
public:
void show() override { // 重写虚函数
std::cout << "派生类 show 函数" << std::endl;
}
};
int main() {
Base* ptr = new Derived();
ptr->show(); // 调用派生类的 show 函数
delete ptr;
return 0;
}
9. 纯虚函数
纯虚函数是一种特殊的虚函数,用于定义接口。在基类中声明纯虚函数时,需要在函数声明前加上 virtual
关键字和 = 0
。纯虚函数没有函数体,派生类必须重写纯虚函数,否则派生类也将成为抽象类。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18class Base {
public:
virtual void show() = 0; // 纯虚函数
};
class Derived : public Base {
public:
void show() override { // 重写纯虚函数
std::cout << "派生类 show 函数" << std::endl;
}
};
int main() {
Base* ptr = new Derived();
ptr->show(); // 调用派生类的 show 函数
delete ptr;
return 0;
}
10. 内联成员函数
使用 inline
关键字提示编译器将函数展开到调用处。1
2
3
4
5
6
7
8
9
10
11
12class MyClass {
public:
inline void greet() { // 内联成员函数
std::cout << "你好!" << std::endl;
}
};
int main() {
MyClass obj;
obj.greet();
return 0;
}
11. 友元函数
友元函数是类的非成员函数,可以在类内部声明,但在类外部定义。友元函数可以访问类的私有成员和保护成员。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class MyClass {
private:
int value;
public:
MyClass(int v) : value(v) {}
friend void printValue(const MyClass& obj); // 声明友元函数
};
void printValue(const MyClass& obj) { // 定义友元函数
std::cout << "value = " << obj.value << std::endl;
}
int main() {
MyClass obj(10);
printValue(obj); // 调用友元函数
return 0;
}