字面值类
字面值类是可以构造编译期常量的抽象数据类型,比如
class Str{
public:
private:
int x = 3;
};
constexpr Str a;
关于字面值类,我们需要注意以下几点
- 字面值类的数据成员需要是字面值类型
- 如果不使用默认生成的构造函数,那么字面值类需要提供
constexpr
/consteval
构造函数(小心使用consteval
)class Str{ public: constexpr Str(int val) :x(val) {} private: int x = 3; }; constexpr Str a(3);
注意
consteval
表明对应的函数和变量只能在编译期求值,不允许使用运行期的值来进行操作,而constexpr
既可以在编译期求值也可以在运行期求值,取决于具体的条件。 - 字面值类一定要有一个平凡的析构函数(即只能使用默认的析构函数或者自定义构造函数但使用默认的逻辑(
default
))class Str{ public: constexpr Str(int val) :x(val) {} ~Str() = default; private: int x = 3; }; constexpr Str a(3);
- 可以为字面值类提供
constexpr
/consteval
成员函数(小心使用consteval
) - 从C++14起,
constexpr
/consteval
的成员函数默认情况下不再是const
成员函数
成员指针
我们可以像普通的指针类型那样为类的数据成员和成员函数构造相应的指针
- 数据成员指针类型示例:
int A::*
- 成员函数指针类型示例:
int (A::*)
(double) - 成员指针对象赋值的例子:
auto ptr = &A::x
注意域操作符子表达式不能加小括号(否则
A::x
一定要有意义),也就是说&(A::x)
这种写法是不行的 - 成员指针的使用方式
- 对象
.*
成员指针class Str{ public: int x; }; int main() { int Str::* ptr = &Str::x; Str obj; obj.x = 3; std::cout << obj.*ptr << std::endl; }
- 对象指针
->*
成员指针class Str{ public: int x; }; int main() { int Str::* ptr = &Str::x; Str* ptr_obj = new Str(); ptr_obj->x = 3; std::cout << ptr_obj->*ptr << std::endl; }
- 对象
成员指针与bind
交互
使用bind
+成员指针可以构造可调用对象,比如
class Str{
public:
int x;
int y;
void fun(double x){
std::cout << x << std::endl;
}
};
int main() {
auto ptr = &Str::fun;
Str obj;
auto x = std::bind(ptr,obj,100);
x();
}
注意在使用
bind
时一定要传入对应的类的对象
我们还可以基于数据成员指针构造可调用对象,比如
class Str{
public:
int x;
int y;
void fun(double x){
std::cout << x << std::endl;
}
};
int main() {
auto ptr = &Str::x;
Str obj;
obj.x = 3;
auto x = std::bind(ptr,obj);
std::cout << x() << std::endl;
}