当前位置: 首页 > news >正文

C++ 面向对象 - 默认值与常量成员

一、 默认值

在C++中,默认值(Default Value)是一个重要的特性,它可以应用于多个场景,包括函数参数、类成员变量、模板参数、枚举初始化等。掌握默认值的各种用法能让代码更简洁、灵活且可维护。

1. 函数参数的默认值

最常用的默认值场景,允许调用函数时省略某些参数。

1.1 规则与用法
  • 声明时指定默认值(通常在头文件中):
    void greet(const std::string& name = "User");
    
  • 默认参数必须从右向左连续定义
    void foo(int a, int b = 10, int c = 20);  // 正确 ✅
    void bar(int a = 1, int b, int c = 2);    // 错误 ❌(必须从右向左连续)
    

示例

#include <iostream>// 函数声明:第二个参数有默认值"World"
void greet(const std::string& name = "World") {std::cout << "Hello, " << name << "!" << std::endl;
}int main() {greet();        // 输出:Hello, World!(使用默认值)greet("Alice"); // 输出:Hello, Alice!(显式提供值)return 0;
}
1.2 函数重载

默认参数可以简化某些重载情况

示例

void print(int x) { std::cout << x; }
void print(int x, int y = 0) { std::cout << x << " " << y; }// 调用:
print(5);      // 优先匹配 print(int x, int y = 0)
print(5, 10);  // 匹配第二个

注意:如果默认参数和重载有二义性,编译器会报错:

void foo(int x = 0);
void foo();
foo();  // 错误!不知道调用哪个
1.3 注意事项
  • 默认值在声明中指定:通常在函数声明(头文件)中指定默认值,定义时不需要重复(否则可能冲突)。
  • 从右向左设置默认值:只能从右到左连续设置默认参数,不能跳过中间的参数。
  • 避免与函数重载冲突:使用默认值可以函数重载。
    greet("Alice", "Hi");  // 错误,如果想用第二个参数的默认值,不能直接跳过第一个
    

2. 类成员变量的默认值

  • 可以在类定义中为成员变量提供默认值(C++11起支持)。
  • 构造函数会优先使用初始化列表的值(如果提供了的话),否则用默认值。

三种初始化方式

方式写法特点
默认成员初始化(C++11)int x = 5;适用于所有构造(无参数时)
大括号初始化(C++11)int x{};零初始化(0/nullptr
构造时初始化int x(5);显式指定初始值

示例

class Person {
private:std::string name = "Anonymous"; // 默认初始化int age{};                      // 默认0(大括号初始化)public:Person() {}  // 若未显式初始化,name="Anonymous", age=0Person(std::string n, int a) : name(n), age(a) {}  // 覆盖默认值
};

3. 模板参数的默认值

模板类或模板函数也可以为类型参数指定默认值(类似函数默认参数)。
示例

template <typename T = int, int Size = 10>  // 默认类型=int,默认大小=10
class Array {
private:T data[Size];
};int main() {Array<> arr1;          // 使用默认值:Array<int, 10>Array<double, 5> arr2; // 显式指定:Array<double, 5>return 0;
}

4. 函数对象(仿函数)的默认值

可以为函数对象的重载operator() 指定默认参数。

示例

struct Adder {int operator()(int a, int b = 10) {return a + b;}
};int main() {Adder add;std::cout << add(5);     // 输出15 (5 + 默认10)std::cout << add(5, 3);  // 输出8 (5 + 3)return 0;
}

5. 总结

用途适用场景语法例子
函数参数简化调用,提供可选参数void foo(int a = 0);
类成员变量C++11+默认初始化int x = 5; / int y{};
模板参数指定默认类型/非类型参数template <typename T = int>
函数对象自定义默认参数int operator()(int a = 0);
默认初始化避免未定义行为int x{};x=0

🚫 注意事项:

  • 默认参数不能跳过中间的参数(必须从右向左)。
  • 默认值和函数重载必须避免二义性
  • 全局变量默认初始化为零,局部变量未定义

二、 常量成员

在C++中,常量成员(const member)是一种特殊的类成员,它可以分为两类:常量成员变量常量成员函数。理解和使用好常量成员对于编写健壮、安全的C++代码非常重要。

常量成员

  • 常量成员变量:由const修饰的成员变量,其值不可修改。

    const 类型 成员变量名
    
  • 常量成员函数:由const修饰的成员函数,其内不可修改对象成员变量的值。

     返回类型 函数名() const {}
    

1. 常量成员变量

1.1 基本概念

常量成员变量是指在类内部声明的、值不能被修改的成员变量。

1.2 声明方式
class MyClass {
public:const int constVar;  // 常量成员变量
};
1.3 初始化方法

常量成员变量有两种初始化方法:

  1. 默认值:可以使用默认值对类的const成员进行初始化。
  2. 构造函数初始化列表:必须在构造函数初始化列表中进行初始化,不能在构造函数体内赋值。

const 成员变量若没有默认值,就必须通过构造函数初始化。一旦初始化后,便不能再修改。
示例

class MyClass {
public:const int constVar1;const int constVar2 = 3;	// 默认值初始化MyClass(int value) : constVar1(value) {  // 正确:在初始化列表中初始化// constVar = value;  // 错误:不能在构造函数体内赋值}// 拥有默认值的常量成员,亦可在初始化列表中初始化MyClass(int value1, int value2) : constVar1(value1), constVar2(value2) {}
};
1.4 特点
  • 一旦初始化后,值不可改变
  • 必须在构造函数初始化列表中初始化
  • 通过构造函数初始化,不同对象的常量成员变量可以拥有不同的值。
1.5 使用场景

用在每个对象都拥有各自不同的不可修改的属性值,这个属性值在对象创建的时候就被确定。

  • 用于表示对象生命周期内不会改变的属性
  • 提高代码安全性,防止误修改

2. 常量成员函数

常量成员函数是一种不会修改对象状态的函数。在常量成员函数体内不允许修改成员变量。但C++也提供了例外,允许在常量成员函数中修改被 mutable 修饰的成员变量

2.1 基本概念

常量成员函数是指在函数声明和定义后加const关键字的成员函数。

2.2 声明方式
class MyClass {
public:void normalFunc();        // 普通成员函数void constFunc() const;   // 常量成员函数
};
2.3 定义

常量成员函数用于保证该函数不会修改对象的状态。当你有一个const对象或对象的引用/指针是const时,只能调用const成员函数。
若类未提供足够的 const 函数,const对象的可用操作会受限。

示例

class MyClass {
public:int value;void setValue(int v) { value = v; }int getValue() const { return value; }  // const成员函数
};void func() {const MyClass obj;// obj.setValue(5);  // 错误:const对象不能调用非const成员函数int v = obj.getValue();  // 正确:可以调用const成员函数
}
2.4 特点
  • 常量成员函数不能修改类的任何普通成员变量
  • 常量成员函数可以调用其他常量成员函数
  • 常量成员函数不能调用非const成员函数
  • const对象只能调用const成员函数,不能调用非 const 函数。
2.5 重载规则

C++允许基于const的重载,即可以同时有const和非const版本的同一个函数。

class MyClass {
public:const int& getRef() const { return value; }int& getRef() { return value; }  // 重载版本的普通成员函数int value;
};
2.6 修改mutable修饰成员变量

如果确实需要在const成员函数中修改某些成员变量,可以将其声明为mutable。

class MyClass {
public:mutable int counter;  // 即使在const成员函数中也可以修改void increment() const {counter++;  // 允许修改mutable成员}
};

3. 总结

  1. 常量成员变量可以指定默认值,否则必须在构造函数的初始化列表中初始化,且初始化后不可修改。
  2. 常量成员函数保证不修改类成员,只能被const对象调用。
  3. 合理使用常量成员可以提高代码的安全性和可读性。
  4. mutable关键字提供了在const成员函数中修改特定成员变量的方法。

4. 综合示例

#include <iostream>
using namespace std;class Demo{
private:// 常量成员变量const int a = 9; 	// 常量成员变量默认值int b;mutable int c = 4;    // 成员变量默认值
public:Demo(){}		// 常量成员变量有默认值,构造函数可以不对其进行初始化Demo(int a, int b):a(a),b(b){}	// 常量成员变量只能在初始化列表中初始化
//	Demo(int a){this->a = a;}		// 错误void setB(int b){
//		a = 4;			// 错误,成员函数中不可修改常量成员的值this->b = b;}// 常量成员函数void print()const{cout << "a = " << a << ", ";cout << "b = " << b << ", ";cout << "c = " << c << endl;
//		this->b = 9;   // 错误 常量成员函数中不可修改对象的值。this->c = 10;	// 常量成员函数中可修改对象的mutable成员。}
};int main()
{Demo d;Demo d1(4, 7);// 不同对象拥有不同的成员常量d.setB(3);d.print();d1.print();// 常量对象只能调用const成员函数const Demo d2(5, 12);
//	d2.setB();		// 错误,常量对象不能调用非const成员函数d2.print();
}
http://www.dtcms.com/a/274874.html

相关文章:

  • sensor_msgs中常用的传感器数据格式以及c++操作
  • 数字孪生技术引领UI前端设计新风尚:智能穿戴设备的界面优化
  • MongoDB(一)
  • 用Python和OpenCV从零搭建一个完整的双目视觉系统(六 最终篇)
  • 【9】PostgreSQL 之 vacuum 死元组清理
  • bash脚本-z检查参数是否为空
  • 雨污管网智慧监测系统网络建设方案:基于SD-WAN混合架构的最佳实践
  • 计算机组成原理:以ADD指令为例讲解微指令执行流程
  • SpringCloud之Eureka
  • 当贝桌面_九联UNT403HS_hi3798mv320处理器安卓9优盘刷机和线刷烧录包
  • 第Y7周:训练自己的数据
  • 洛谷P2042 [NOI2005] 维护数列
  • 可以自定义皮肤的桌面备忘便签软件-滴哦小精灵 v1.4.5
  • 深入理解JVM
  • 视频翻译用什么软件?这里有5个高效推荐
  • 编码技术: PRBS, 8B/10B
  • MCU芯片内部的ECC安全机制
  • 提升你的AI交互技能:使用Anthropic互动提示教程
  • c语言中的数组IV
  • Qt:布局管理器Layout
  • flutter鸿蒙版 环境配置
  • Deekseek 学习笔记
  • 北京-4年功能测试2年空窗-报培训班学测开-第四十八天
  • 信创 CDC 实战 | TiDB 实时入仓难点与解决方案解析(以 ClickHouse 为例)
  • 【面板数据】省级泰尔指数及城乡收入差距测算(1990-2024年)
  • 大模型人类反馈强化学习RLHF 凭什么火出圈?人类反馈 + 强化学习,解锁 AI 行为可控密码
  • 盛世美颜伴杭州--花皙蔻牡丹盛世美颜精华油获选“2025杭州特色伴手礼”
  • 【Quest开发】快速添加可手指触摸按钮
  • unity VR linerenderer的线会被UI盖住
  • 微算法科技基于格密码的量子加密技术,融入LSQb算法的信息隐藏与传输过程中,实现抗量子攻击策略强化