function
模板函数 使如下代码可以正常运行:
#include
using namespace std;
int add(int a, int b) {
return a + b;
}
class ADD_MULT {
public:
ADD_MULT(int x) : x(x) {}
int operator() (int a, int b) {
return (a + b) * 2;
}
int x;
};
int main() {
ADD_MULT add_mult(2);
function f1 = add;
function f2 = add_mult;
cout << f1(3, 4) << endl;
cout << f2(3, 4) << endl;
f1 = f2;
cout << f1(3, 4) << endl;
f1 = add;
f2 = add_mult;
cout << f1(3, 4) << endl;
cout << f2(3, 4) << endl;
return 0;
}
function
模板样式:template class function {};
template
class function {
public:
};
这里使用模板的偏特化,来实现需求
我们想要用同一个数据类型来同时接受两种不同的对象,这里就得使用**继承(接口)**来实现,
template
class BASE {
public:
};
template
class normal_function : public BASE {
public:
};
template
class B : public BASE {
public:
};
template class function {};
template
class function {
public:
function(T (*ptr)(ARGS...)) : ptr(new normal_function(ptr)) {}
template
function(U &u) : ptr(new B(&u)) {}
private:
BASE *ptr;
};
这里我们可以使用BASE
类来同时接受不同函数和对象。并且由于对象的类型是不确定的,所有我们得在类对象的构造函数上面加上模板,来处理这种情况。
template
class normal_function : public BASE {
public:
normal_function(T (*ptr)(ARGS...)) : ptr(ptr) {}
private:
T (*ptr)(ARGS...);
};
我们在这里定义一个函数指针,来接收我们函数地址,并进行初始话。
template
class B : public BASE {
public:
B(U *u) : u(u), ptr(&U::operator()) {}
private:
U *u;
T (U::*ptr)(ARGS...);
};
我们这里定义了一个指针对象,用来记录对象的地址,并定义了一个指向成员函数的指针(因为是虚函数,所有用虚函数表),来记录成员函数的地址。
到这里我们就实现了如何同一个数据类型来同时接受两种不同的对象,也就是主函数中的这段代码:
function f1 = add;
function f2 = add_mult;
cout << f1(3, 4) << endl;
template
class BASE {
public:
virtual T run(ARGS...) = 0;
};
template
class normal_function : public BASE {
public:
normal_function(T (*ptr)(ARGS...)) : ptr(ptr) {}
T run(ARGS... args) override {
return ptr(forward(args)...);
}
private:
T (*ptr)(ARGS...);
};
template
class B : public BASE {
public:
B(U *u) : u(u), ptr(&U::operator()) {}
T run(ARGS... args) override {
return (u->*ptr)(forward(args)...);
}
private:
U *u;
T (U::*ptr)(ARGS...);
};
template class function {};
template
class function {
public:
function(T (*ptr)(ARGS...)) : ptr(new normal_function(ptr)) {}
template
function(U &u) : ptr(new B(&u)) {}
T operator()(ARGS... args) {
return ptr->run(args...);
}
private:
BASE *ptr;
};
这里我们就可以用继承来实现各自的输出:
代码中,BASE
类是一个纯虚基类,定义了一个 run
方法,但没有提供具体的实现。normal_function
和 B
类分别继承自 BASE
,并提供了 run
方法的具体实现。
normal_function
类中,run
方法直接调用了存储的普通函数指针,并将传入的参数通过 forward
转发给该函数。B
类中,run
方法通过类成员指针调用了存储的类成员函数指针,同样使用了 forward
转发参数。 这样,通过继承自 BASE
并在派生类中实现 run
方法,你的 function
类就能够包装不同类型的函数指针了。
在 function
类中,构造函数根据传入的参数类型选择相应的类来实例化,从而实现了对普通函数和类成员函数的封装。operator()
方法最终调用了 run
方法,使得你可以通过 function
对象调用包装的函数。
需要注意的是,代码中使用了 forward
来转发参数,这是为了保留参数的完美转发性质,即传递参数时保留其值类别(lvalue 或 rvalue)和 const 限定符。
f1 = f2;
赋值操作template
class BASE {
public:
virtual T run(ARGS...) = 0;
virtual BASE *getCopy() = 0;
};
template
class normal_function : public BASE {
public:
normal_function(T (*ptr)(ARGS...)) : ptr(ptr) {}
T run(ARGS... args) override {
return ptr(forward(args)...);
}
BASE *getCopy() override {
BASE *fun = new normal_function(ptr);
return fun;
}
private:
T (*ptr)(ARGS...);
};
template
class B : public BASE {
public:
B(U *u) : u(u), ptr(&U::operator()) {}
T run(ARGS... args) override {
return (u->*ptr)(forward(args)...);
}
BASE *getCopy() override {
BASE *fun = new B(u);
return fun;
}
private:
U *u;
T (U::*ptr)(ARGS...);
};
template class function {};
template
class function {
public:
function(T (*ptr)(ARGS...)) : ptr(new normal_function(ptr)) {}
template
function(U &u) : ptr(new B(&u)) {}
T operator()(ARGS... args) {
return ptr->run(args...);
}
function &operator=(const function &fun) {
delete ptr;
this->ptr = fun.ptr->getCopy();
return *this;
}
~function() {
delete ptr;
}
private:
BASE *ptr;
};
赋值操作符首先删除当前对象 (this
) 的 ptr
指针指向的对象
然后通过调用 fun.ptr->getCopy()
来获取 fun
对象的一个副本,并将其赋值给当前对象的 ptr
这里 getCopy
方法是一个虚函数,它在基类 BASE
中声明并在派生类中实现。在派生类中,getCopy
的实现会创建一个新的对象,该对象的类型是当前派生类,然后返回这个新对象的指针。
赋值操作符实际上是在进行深拷贝,确保两个 function
对象之间不共享相同的函数对象。这里使用了虚函数 getCopy
来创建副本,而不是简单的指针复制。这可以防止在两个 function
对象中的 ptr
指针指向相同的内存位置,从而避免在一个对象的析构时影响另一个对象。
这是我们就基本完成了function
模板函数的基本功能。
/*************************************************************************
> File Name: test.cpp
> Author:Xiao Yuheng
> Mail:[email protected]
> Created Time: Thu Nov 16 19:37:14 2023
************************************************************************/
#include
using namespace std;
template
class BASE {
public:
virtual T run(ARGS...) = 0;
virtual BASE *getCopy() = 0;
};
template
class normal_function : public BASE {
public:
normal_function(T (*ptr)(ARGS...)) : ptr(ptr) {}
T run(ARGS... args) override {
return ptr(forward(args)...);
}
BASE *getCopy() override {
BASE *fun = new normal_function(ptr);
return fun;
}
private:
T (*ptr)(ARGS...);
};
template
class B : public BASE {
public:
B(U *u) : u(u), ptr(&U::operator()) {}
T run(ARGS... args) override {
return (u->*ptr)(forward(args)...);
}
BASE *getCopy() override {
BASE *fun = new B(u);
return fun;
}
private:
U *u;
T (U::*ptr)(ARGS...);
};
template class function {};
template
class function {
public:
function(T (*ptr)(ARGS...)) : ptr(new normal_function(ptr)) {}
template
function(U &u) : ptr(new B(&u)) {}
T operator()(ARGS... args) {
return ptr->run(args...);
}
function &operator=(const function &fun) {
delete ptr;
this->ptr = fun.ptr->getCopy();
return *this;
}
~function() {
delete ptr;
}
private:
BASE *ptr;
};
int add(int a, int b) {
return a + b;
}
class ADD_MULT {
public:
ADD_MULT(int x) : x(x) {}
int operator() (int a, int b) {
return (a + b + x) * 2;
}
int x;
};
int main() {
ADD_MULT add_mult(2);
function f1 = add;
function f2 = add_mult;
cout << f1(3, 4) << endl;
cout << f2(3, 4) << endl;
f1 = f2;
cout << f1(3, 4) << endl;
f1 = add;
f2 = add_mult;
cout << f1(3, 4) << endl;
cout << f2(3, 4) << endl;
return 0;
}
/*************************************************************************
> File Name: test.cpp
> Author:Xiao Yuheng
> Mail:[email protected]
> Created Time: Thu Nov 16 19:37:14 2023
************************************************************************/
#include
#include
using namespace std;
int add(int a, int b) {
return a + b;
}
class ADD_MULT {
public:
ADD_MULT(int x) : x(x) {}
int operator() (int a, int b) {
return (a + b + x) * 2;
}
int x;
};
int main() {
ADD_MULT add_mult(2);
function f1 = add_mult;
cout << f1(2, 3) << endl;
add_mult.x = 10;
cout << f1(2, 3) << endl;
return 0;
}
我们在这里试着调用functional
中的function
模板函数,这里我们试着更改add_mult.x = 10;
这个的值,然后再次输出:我们输出一下,看看结果:
可以发现值并没有发生变化,而我们用我们实现的代码来运行一下这段代码:
可以发现是会变化的,因为我们上面用的是指针来实现的,我们来进行修改(虽然我认为按照我的思路来说,修改了才是对的):
/*************************************************************************
> File Name: test1.cpp
> Author:Xiao Yuheng
> Mail:[email protected]
> Created Time: Thu Nov 16 20:02:50 2023
************************************************************************/
#include
using namespace std;
template
class BASE {
public:
virtual T run(ARGS...) = 0;
virtual BASE *getCopy() = 0;
};
template
class normal_function : public BASE {
public:
normal_function(T (*ptr)(ARGS...)) : ptr(ptr) {}
T run(ARGS... args) override {
return ptr(forward(args)...);
}
BASE *getCopy() override {
BASE *fun = new normal_function(ptr);
return fun;
}
private:
T (*ptr)(ARGS...);
};
/*
template
class B : public BASE {
public:
B(U *u) : u(u), ptr(&U::operator()) {}
T run(ARGS... args) override {
return (u->*ptr)(forward(args)...);
}
BASE *getCopy() override {
BASE *fun = new B(u);
return fun;
}
private:
U *u;
T (U::*ptr)(ARGS...);
};
*/
template
class B : public BASE {
public:
B(U u) : u(u) {}
T run(ARGS... args) override {
return u(forward(args)...);
}
BASE *getCopy() override {
return new B(u);
}
private:
U u;
};
template class function {};
template
class function {
public:
function(T (*ptr)(ARGS...)) : ptr(new normal_function(ptr)) {}
template
function(U &u) : ptr(new B(u)) {}
T operator()(ARGS... args) {
return ptr->run(args...);
}
function &operator=(const function &fun) {
delete ptr;
// this->ptr = fun.ptr;
this->ptr = fun.ptr->getCopy();
return *this;
}
~function() {
delete ptr;
}
private:
BASE *ptr;
};
int add(int a, int b) {
return a + b;
}
class ADD_MULT {
public:
ADD_MULT(int x) : x(x) {}
int operator() (int a, int b) {
return (a + b) * 2;
}
int x;
};
int main() {
ADD_MULT add_mult(2);
function f1 = add;
function f2 = add_mult;
cout << f1(3, 4) << endl;
cout << f2(3, 4) << endl;
f1 = f2;
cout << f1(3, 4) << endl;
f1 = add;
f2 = add_mult;
cout << f1(3, 4) << endl;
cout << f2(3, 4) << endl;
return 0;
}
我们这里的B
类的构造函数之间用一个B类的对象来继续接收就欧克了。