有没有办法将对象的字段隐式传递给函数C++
Is there a way to pass an object's field implicitly to a function in C++
假设我有一个对象
class Obj {
public:
int a;
int b;
int c;
}
和一组对象
Obj o[N];
我想把每个Obj.a复制到一个int数组中,我知道其他语言允许我在C++中生成一个函数,它可能看起来像这样
int & fun(Obj os[], T key, int N){
int a[N];
for (int i=0; i<N; i++) {
a[i] = os[i].key;
}
return a;
}
在C++中有什么可重复使用的方法吗?作为参考,Obj的代码不能修改。
这就是std::transform
函数的作用。您所需要提供的只是一个从Obj
中获取所需元素的函数。此示例显示如何使用std::mem_fn
:
#include <algorithm>
#include <functional>
#include <iterator>
#include <iostream>
struct Obj { int a, b, c; };
int main() {
Obj o[3] = {{1, 2, 3}, {11, 22, 33},{111, 222, 333}};
int a[3];
std::transform(std::begin(o), std::end(o),
std::begin(a),
std::mem_fn(&Obj::a));
for (auto e : a)
std::cout << e << ' ';
std::cout << std::endl;
};
输出:
1 11 111
这一切都可以封装在一个助手函数中,以允许调用方设置要提取的属性。但请注意,如果您真的希望函数返回数组,则需要使用可复制类型,如std::array
或std::vector
。在C++中,普通数组是不可复制的,因此不能由函数的值返回。
这里有一个稍微修改过的代码版本:
#include <cstddef>
#include <iostream>
using std::size_t;
struct Obj {
int a;
int b;
int c;
};
static void fun(const Obj *os, size_t N, int Obj::*const key) {
for (size_t i = 0; i < N; i++) {
std::cout << os[i].*key << 'n';
}
}
int main() {
Obj o[] = { {1, 2, 3}, {4, 5, 6} };
fun(o, sizeof o / sizeof o[0], &Obj::b);
}
我更改了fun
的返回类型,因为您的版本没有进行类型检查。出于演示目的,fun
只是输出元素。
这里的关键是,您可以通过使用成员指针对类字段进行抽象。
您可以使用指向成员的指针语法:
#include <iostream>
#include <memory>
struct Obj {
int a;
int b;
};
std::unique_ptr<int[]>
fn(Obj* os, size_t N, int Obj::*member)
{
auto arr = std::make_unique<int[]>(N);
for (size_t i = 0; i < N; ++i) {
arr[i] = os[i].*member;
}
return arr;
}
int main() {
Obj os[] { { 1, 10 }, { 2, 20 } };
auto a1 = fn(os, 2, &Obj::a);
auto a2 = fn(os, 2, &Obj::b);
for (size_t i = 0; i < 2; ++i) {
std::cout << i << ": " << a1[i] << ", " << a2[i] << 'n';
}
}
演示:http://ideone.com/cQMyh3
或者你可以使用lambda。
#include <iostream>
#include <memory>
struct Obj {
int a;
int b;
};
std::unique_ptr<int[]>
fn(Obj* os, size_t N, std::function<int(const Obj&)> keyFn)
{
auto arr = std::make_unique<int[]>(N);
for (size_t i = 0; i < N; ++i) {
arr[i] = keyFn(os[i]);
}
return arr;
}
int main() {
Obj os[] { { 1, 10 }, { 2, 20 } };
auto a1 = fn(os, 2, [](const Obj& o){ return o.a; });
auto a2 = fn(os, 2, [](const Obj& o){ return o.b; });
for (size_t i = 0; i < 2; ++i) {
std::cout << i << ": " << a1[i] << ", " << a2[i] << 'n';
}
}
http://ideone.com/9OvTzl
或者更通用的:
template<typename KeyFn>
std::unique_ptr<int[]>
fn(Obj* os, size_t N, KeyFn keyFn)
{
auto arr = std::make_unique<int[]>(N);
for (size_t i = 0; i < N; ++i) {
arr[i] = keyFn(os[i]);
}
return arr;
}
其他需要考虑的变化:
- 使用标准容器,例如
vector
或array
来容纳对象 - 考虑在范围上传递迭代器,而不是指针和大小
使用范围库,您可以简单地执行
for (int e : objs | ranges::v3::view::transform(&Obj::a)) {
std::cout << e << " ";
}
演示
您的例子在C++中的一个可能的转录可能是:
#include <functional>
int* fun(Obj os[], std::function<int(Obj)> get_key, int N){
int* a = new int[N];
for (int i=0; i<N; i++) {
a[i] = get_key(os[i]);
}
return a;
}
用途:
func(os, [](Obj obj){return obj.a;}, N);
您必须声明一个动态数组,因为大小是可变的。但是使用原始指针,可能会出现内存泄漏或分段错误。带有托管指针的版本(仅适用于C++14):
#include <memory>
#include <functional>
std::unique_ptr<int[]> fun(Obj os[], std::function<int(Obj)> get_key, int N){
std::unique_ptr<int[]> a = std::make_unique(N);
for (int i=0; i<N; i++) {
a[i] = get_key(os[i]);
}
return a;
}
或者使用stl容器(无内存分配):
#include <vector>
#include <functional>
std::vector<int> fun(Obj os[], std::function<int(Obj)> get_key, int N){
std::vector<int> a(N);
for (int i=0; i<N; i++) {
a[i] = get_key(os[i]);
}
return a;
}
但从一种语言"翻译"到另一种语言通常是个坏主意;)
相关文章:
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 内置函数可查看CPP中的成员变量
- 如何获取std::result_of函数的返回类型
- 如何在c++中为模板函数实例创建快捷方式
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗