在c++中,我可以重置操作符的函数指针
In C++ can I reset the function pointer for an operator?
在c++中,我可以重置操作符的函数指针吗?
特别地,我想设置成员函数operator[]使用(或不使用)边界检查。我试了一下,没有运气:
这可能吗?如果有,有人能纠正语法吗?
in MyArrayClass.h:
class MyArrayClass {
public:
bool CheckArrayBounds;
float BoundsCheck(int i) {
if (i<_size)
return _data[i];
return TCpx(_INVALID);
}
float NoBoundsCheck(int i) {
return _data[i];
}
void UseBoundsCheck(bool State) {
if (State) {
float (operator[]) = &MyArrayClass::BoundsCheck;
} else {
float (operator[]) = &MyArrayClass::NoBoundsCheck;
}
CheckArrayBounds = State;
}
float operator[](int i) { return _data[i]; };
};
这不可能。从语义上讲,成员函数不是函数指针(尽管它们可以在底层以这种方式实现)。
您可以在operator[] ()
中对State
执行检查,或者使用代理对象
您不能在运行时更改特定对象实例的操作符,因为成员函数与对象属性分开存储,并且对于所有对象实例都是相同的。它们被存储在写保护内存段中。或者甚至可以由编译器内联。
仍然可以检查操作符[]实现内部的状态。
也可以创建属性at
并替换操作符
class MyArrayClass {
public:
float (MyArrayClass::*at)(int i);
float BoundsCheck(int i);
float NoBoundsCheck(int i); {
void UseBoundsCheck(bool State) {
at = (State)? &MyArrayClass::BoundsCheck : &MyArrayClass::NoBoundsCheck;
}
};
用法:
MyArrayClass a;
a.at( 1 );
No.
方法(和运算符只是方法/函数的语法糖)是在编译时定义的,而不是在运行时定义的。
c++不是适合这种情况的语言。你需要一个更强大的类型系统。
请注意,即使可以,也可能会降低程序的速度:整数比较比通过指针调用函数要昂贵得多。特别是因为你的CPU可以分支预测:它将开始运行代码,如果它通过了检查,如果它最终失败,它可以放弃它正在做的任何事情。
但是注意你的编译器是聪明的。例如,如果我们这样写:
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <vector>
void process(std::vector<int>& data)
{
for (unsigned i = 0; i < data.size(); ++i)
{
int v = data.at(i);
std::cout << v << std::endl;
}
}
int main()
{
try
{
std::vector<int> data;
std::generate_n(std::back_inserter(data), std::rand() + 1, std::rand);
process(data);
}
catch (...)
{
std::cerr << "nope.avi" << std::endl;
}
}
如果用g++ -O3
编译,没有边界检查代码。实际上,编译器已经推断出at()
中的检查永远不会通过(然后抛出),因此它剥离了该代码。因此,您可以保留边界检查,而编译器仍然可以剥离它。但请注意,任何更复杂的情况都可能使编译器难以证明,因此您将为此付出代价。
这些都是你可以用更有表现力的类型系统来保证的优化,但是编译器无论如何都可以做到。我不知道MSVC;它往往不那么聪明,但你可以检查一下。
您最好的选择是走std::vector<>
路线:提供未检查的operator[]
和已检查的at()
。让你的类的用户决定他们是否需要检查
函数和成员函数实际上是常量或不可变的,并且不可能在运行时更改它们。然而,对于你想要做的事情,有一种半途而废的方法,而你在发布的代码中几乎已经实现了。
你所能做的就是定义一个指向成员函数的指针,然后在运行时根据你是否想要激活边界检查来改变指针的值。
class MyArrayClass {
public:
typedef float (MyArrayClass::*AccessFn)(int i);
AccessFn Access;
bool CheckArrayBounds;
float BoundsCheck(int i) {
if (i<_size)
return _data[i];
return TCpx(_INVALID);
}
float NoBoundsCheck(int i) {
return _data[i];
}
MyArrayClass() { UseBoundsCheck(false); }
void UseBoundsCheck(bool State) {
if (State) {
Access = &MyArrayClass::BoundsCheck;
} else {
Access = &MyArrayClass::NoBoundsCheck;
}
CheckArrayBounds = State;
}
float operator[](int i) { return (this->*Access)(i); }
};
这是我能想到的最接近你要求的方法了
- 我可以将C 17 Capture lambda ConstexPR转换操作符的结果用作函数指针模板非类型参数吗?
- 当delete操作符释放内存时,我为什么需要析构函数
- 为什么操作符的新函数需要强制转换
- 如何使操作符的左操作数<<一个函数
- 如何重载操作符==外模板类使用友元函数
- 在泛型函数中没有匹配操作符==
- Assert()函数抛出一个错误——操作符有问题
- 删除操作符,它们等同于c++中的析构函数
- 复制构造函数,赋值操作符重载
- 强制转换操作符函数在g++中可以很好地编译,但在其他编译器中不行.为什么
- 通过调用Move赋值操作符实现Move构造函数
- 在类赋值操作符函数中,为什么必须返回*this ?
- 有没有一种方法可以通过函数指针来调用操作符函数?
- 如何为代理类实现相等操作符函数
- 如何为嵌套类编写范围解析操作符函数头
- 类不能包含内部定义枚举的操作符函数
- 从结构指针调用重载操作符函数
- 操作符函数和与之相关的编译错误
- 带有指向对象指针的操作符函数
- 复制和交换技术在赋值操作符函数内部使用复制构造函数