相当于 Objective-C 在 C++ 中的"valueForKey"方法?
An equivalent of Objective-C's "valueForKey" methodology in C++?
假设我们有一个 Objective-C NSArray
Shoe
类或Computer
类的实例。这两个类都有方法 age
.
Objective-C将允许您通过一个简单的语句获得所有鞋子和计算机的年龄,如下所示:
NSArray *agesOfShoesAndComputers = [ourArray valueForKey:@"age"];
C++是否有任何类似的方法可以应用于向量,或者像这样的东西在C++中总是更麻烦吗?
首先,std::vector<T>
是静态类型的。也就是说,您需要在编译时知道它是否包含鞋子或计算机。
所以,简短的回答是,C++总是会更麻烦(静态类型实际上是一种优化,所以这是我们为性能付出的代价)。
如果要使用传统的运行时多态性,则需要一个通用基类:
class MyBase
{
public:
virtual ~MyBase();
virtual int age() = 0;
};
class Shoe: public MyBase
{
public:
virtual int age();
};
// same for Computer
现在我可以拥有
std::vector<std::unique_ptr<MyBase>> ourArray;
和
std::vector<int> ages(std::vector<std::unique_ptr<MyBase>> const &ourArray)
{
std::vector<int> ages;
std::transform(ourArray.begin(), ourArray.end(),
std::back_inserter<int>(ages),
[](std::unique_ptr<MyBase> const& elem) { return elem->age(); }
);
return ages;
}
这里对elem->age()
的调用依赖于MyBase
定义的公共接口,但调度到派生类实现(分别为Shoe::age()
和Computer::age()
)。
它不如 Objective C 版本灵活,因为您的通用接口、继承等都是静态定义的。
请注意,如果这是一个简单的属性,则可以完全跳过虚拟方法调用并将其放入MyBase
。鞋子和计算机仍然需要从此类继承,但它们只能在基类中设置属性值。
您可以改用编译时多态性,即模板。这在某些方面更类似于 Objective C 方法,因为它适用于支持预期方法的任何类型,而不考虑继承关系。
template <typename T> // T could be Shoe, Computer or anything else
std::vector<int> ages(std::vector<T> const &ourArray)
{
std::vector<int> ages;
std::transform(ourArray.begin(), ourArray.end(),
std::back_inserter<int>(ages),
[](T const& elem) { return elem.age(); }
);
return ages;
}
不过,机制完全不同——你仍然有静态不同的调用站点,要么是vector<Shoe>
,要么是vector<Computer>
,要么是其他什么,而且吐温永远不会见面。
动态性稍差,但您要查找的内容通常transform
:
vector<unique_ptr<BaseClassForShoeAndComputer>> ourArray;
vector<int> agesOfShoesAndComputers;
transform(ourArray.begin(), ourArray.end(),
back_inserter(agesOfShoesAndComputers),
[](unique_ptr<BaseClassForShoeAndComputer>& s) { return s->age(); });
但是,您不能在单个容器中真正拥有不相关的对象(嗯,您可以,但使用它们是另一回事);但是,您可以使用模板(不幸的是,不是与lambda一起使用)来实现静态鸭子类型(用于任何带有"age"方法的类型)。
如果您的编译器不支持lambdas
您可以使用<functional>
(但无论如何使用 c++ 11)
std::vector<std::shared_ptr<Base>> v;
std::vector<int> ages;
std::transform(v.begin(),
v.end(),
std::back_inserter(ages),
std::bind(&Base::getAge, std::placeholders::_1));
其中Base
是Shoe
和Computer
的基类
您还可以使用模板从支持getAge()
函数的任何类型中获取年龄。
template <typename InputIterator>
static std::vector<int> getAges(InputIterator start, InputIterator finish)
{
typedef typename InputIterator::value_type T;
std::vector<int> ages;
std::transform(start,
finish,
std::back_inserter(ages),
std::bind(&T::getAge, std::placeholders::_1));
return ages;
}
int main()
{
std::vector<Base> v;
std::vector<int> ages = getAges(v.begin(), v.end());
}
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 没有为自己的结构调用列表推回方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 在类定义之后定义一个私有方法
- 枚举环境变量的惯用C++14/C++17方法
- 相当于 Objective-C 在 C++ 中的"valueForKey"方法?