在C++中相当于Objective-C的"valueForKey"方法?

Noo*_*low 2 c++ objective-c

假设我们有一个Objective-C 类或类NSArray的实例.这两个类都有这个方法.ShoeComputerage

Objective-C允许您在一个简单的声明中获得所有鞋子和计算机的年龄,如下所示:

NSArray *agesOfShoesAndComputers = [ourArray valueForKey:@"age"];
Run Code Online (Sandbox Code Playgroud)

C++是否有任何类似的方法可以应用于矢量,或者像C这样的东西在C++中总是有点麻烦?

Use*_*ess 6

首先,std::vector<T>静态类型.也就是说,您需要在编译时知道它是否包含鞋子或计算机.

所以,简短的回答是它在C++中总是比较麻烦(静态类型实际上是一种优化,所以这是我们为性能付出的代价).


如果要使用传统的运行时多态性,则需要一个公共基类:

class MyBase
{
public:
    virtual ~MyBase();
    virtual int age() = 0;
};

class Shoe: public MyBase
{
public:
    virtual int age();
};
// same for Computer
Run Code Online (Sandbox Code Playgroud)

现在我可以拥有

std::vector<std::unique_ptr<MyBase>> ourArray;
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

该机制是完全不同的东西-你仍然有静态与不同的调用点无论是 vector<Shoe> vector<Computer>或什么的,两者永远不相遇.