请教cppreference中默认实参规则里非静态类成员例外条款的含义及示例代码
关于C++默认实参中非静态类成员例外规则的解释与示例
嘿,我来帮你把cppreference里这条规则的例外情况讲透,结合代码示例你就能一目了然了!
先回顾一下原规则:
非静态类成员不允许用于默认实参(即使它们不会被求值),除非用于形成指向成员的指针(pointer-to-member)或在成员访问表达式中:
下面分别解释这两个例外场景,并给出对应的代码示例:
1. 例外场景一:用于形成指向成员的指针
指向成员的指针(不管是数据成员还是成员函数)本质上是一种编译期确定的类型信息,它描述的是成员在类中的位置,而不是依赖某个具体对象的成员值。所以把非静态成员用来构造这种指针时,是允许作为默认实参的。
示例1:指向非静态成员函数的指针作为默认实参
class X { private: void nonstatic_mem_func() {} public: // 合法:默认实参是指向非静态成员函数的指针 void set_callback(void (X::*callback)() = &X::nonstatic_mem_func) { // 使用时需要绑定具体对象,比如(this->*callback)(); } };
示例2:指向非静态数据成员的指针作为默认实参
class X { private: int nonstatic_data = 42; public: // 合法:默认实参是指向非静态数据成员的指针 void print_member(int X::*data_ptr = &X::nonstatic_data) { std::cout << this->*data_ptr << std::endl; } }; // 使用方式 X obj; obj.print_member(); // 输出42
2. 例外场景二:在成员访问表达式中
这里的关键是,你必须通过明确的对象实例来访问非静态成员,编译器能确定这个访问是合法的(不需要依赖未定义的对象)。最常见的就是在非静态成员函数中使用this->成员,因为每个非静态成员函数调用时都会绑定到具体对象,this是确定的;另外也可以访问全局/命名空间级别的类对象的非静态成员。
示例1:使用this->成员作为默认实参
class X { private: int nonstatic_data = 100; public: // 合法:默认实参是this->nonstatic_data,属于成员访问表达式 int get_value(int val = this->nonstatic_data) { return val; } }; // 使用方式 X obj; std::cout << obj.get_value() << std::endl; // 输出100
示例2:访问全局对象的非静态成员作为默认实参
class GlobalObj { public: int global_nonstatic = 200; }; GlobalObj global_instance; class Y { public: // 合法:默认实参是global_instance.global_nonstatic,属于成员访问表达式 void print_global_val(int val = global_instance.global_nonstatic) { std::cout << val << std::endl; } }; // 使用方式 Y y_obj; y_obj.print_global_val(); // 输出200
总结
这两个例外的核心逻辑是:要么你传递的是不依赖具体对象的成员指针(只是描述成员的位置),要么你是通过确定存在的对象实例来访问非静态成员,这样编译器就能确保默认实参的合法性,不会出现“引用了未绑定到对象的非静态成员”的问题。
内容的提问来源于stack exchange,提问作者LandP
相关产品推荐
相关产品推荐

