![](/img/trans.png)
[英]Is there a C++ equivalent to objective-c's -debugDescription method for Xcode 7?
[英]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这样的东西在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
。 Shoes和Computers仍然需要从这个类继承,但是他们只需要在基类中设置属性值。
您可以使用编译时多态,即模板。 这在某些方面更类似于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>
或者其他任何东西,而且twain不会满足。
C ++的动态性稍差,但您所寻找的通常是transform
:
vector<unique_ptr<BaseClassForShoeAndComputer>> ourArray;
vector<int> agesOfShoesAndComputers;
transform(ourArray.begin(), ourArray.end(),
back_inserter(agesOfShoesAndComputers),
[](unique_ptr<BaseClassForShoeAndComputer>& s) { return s->age(); });
但是,你不能在一个容器中真正拥有不相关的对象(嗯,你可以,但是使用它们是另一回事); 但是,你可以使用模板(不幸的是,不使用lambdas)来实现静态鸭子类型(用于任何带有“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
and 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());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.