【问题标题】:How to write a getter for a type in C++ without undefining the type?如何在不取消定义类型的情况下为 C++ 中的类型编写 getter?
【发布时间】:2017-10-17 21:03:21
【问题描述】:

我有一个实现接口的对象集合,我希望在它上面有 getter 以获取仅在 C++ 中的单个实现。在 Java 中,我会这样做:

interface IFooBar { }
class Foo implements IFooBar { }
class Bar implements IFooBar { }

class Container extends HashSet<IFooBar> {

    public Container() { }
    public Container(Collection<? extends IFooBar> c) { super(c); }

    Foo getFoo() {
        return getFoos().iterator().next();
    }

    Set<Foo> getFoos() {
        HashSet<Foo> result = new HashSet<>();
        for(IFooBar item:this) if (item instanceof Foo) result.add((Foo) item);
        return result;
    }

    Bar getBar() { /* ... same ... */ }

    Set<Bar> getBars() { /* ... same ... */ }
}

现在我尝试在 C++ 中做同样的事情。对于项目要求,我必须使用我的对象的shared_ptr&lt;&gt;。这是我走了多远:

class IFooBar { }
class CFoo : IFooBar { }
class CBar : IFooBar { }

class CContainer {
public:
    CContainer();
    CContainer(std::vector<const std::shared_ptr<IFooBar>> cPrivData);

    const std::shared_ptr<CFoo> CFoo();
    std::vector<const std::shared_ptr<CFoo>> CFoos();
                                   /* ^^^^ : Function CContainer::CFoo is not a type name */
    const std::shared_ptr<CBar> CBar();
    std::vector<const std::shared_ptr<CBar>> CBars();

private:
    std::vector<const std::shared_ptr<IObject>> m_cPrivData;
};

显然这是行不通的,我不能给吸气剂起它应该有的名字(我认为)。我收到指示的错误。该函数似乎未定义类型名称。现在我想知道哪个是我在 C++ 中给出的 Java 示例的直观可用的实现? 或者,推荐的 getter 名称是什么?我了解到,在 C++ 中,getter 的命名不带“get”,函数名以大写开头。我希望 getter 反映它返回的类类型。

也许我应该完全走另一条路?我可以定义一个赋值构造函数,而不是函数CFoo(),如果可以,如何?我是否必须超载shared_ptr&lt;&gt; 才能这样做?如果是这样,怎么做?我的想法是这样的:

class CSharedFooBarPointer : std::shared_pointer<IFooBar> {
public:
    shared_ptr<Foo> operator=(std::vector<const std::shared_ptr<IFooBar>>& cContainer);
    shared_ptr<Bar> operator=(std::vector<const std::shared_ptr<IFooBar>>& cContainer);
}

(也许我觉得这里太 Java 了,但我对 C++ 还是很陌生。)也许这种方法不好,因为也许我不能内联使用它。或者我可以吗?从上面的 Java 示例中,我希望能够执行 container.getFoo().doSomethingFooSpecific(); 之类的操作。在 C++ 中,我必须使用什么语法?有类似((CFoo)cContainer).DoSomethingFooSpecific(); 的东西吗?如果我只使用一次,我不想分配一个变量,如果可能的话。

【问题讨论】:

  • 什么是IObject
  • 另外,C++ 并没有真正每个人都遵循的通用代码约定,我经常看到以Get 开头的方法名称。
  • 名称冲突可以通过添加'::'来解决。喜欢const std::shared_ptr&lt;::CFoo&gt; CFoo();

标签: c++ inheritance interface shared-ptr getter


【解决方案1】:

注意:此答案中的代码未经测试,可能包含拼写错误。

我了解到在 C++ 中,getter 的命名不带“get”前导,并且函数名以大写开头。

据我所知。但是正如Gill Bates 所提到的,C++ 没有集中的样式指南,所以只需选择一种代码样式并坚持下去。我个人从来没有见过在 ol' MFC 和 WINAPI 之外以大写字母开头的函数——你可能会想到 C#。 C 类前缀同上。

在任何情况下,名称冲突都可以通过scope resolution operator :: 解决:

class CContainer {
    // ...
    const std::shared_ptr<CFoo> CFoo();
    std::vector<const std::shared_ptr<::CFoo>> CFoos();
    //     CFoo from the global scope ^^
    // ...
};

在实现功能方面领先一步:
要在运行时确定对象的动态类型,您需要 dynamic_cast,或者在您的情况下需要 std::dynamic_pointer_cast 辅助函数。

std::vector<const std::shared_ptr<::CFoo>> CContainer::CFoos() {
    std::vector<const std::shared_ptr<::CFoo>> result;

    for(auto const &objPtr : m_cPrivData)
        if(auto fooPtr = std::dynamic_pointer_cast<::CFoo>(objPtr))
            result.push_back(std::move(fooPtr));

    return result;
}

但是,dynamic_cast 要求对象的类型是多态的,这意味着IFooBar 需要至少有一个虚成员函数。如果没有足够的函数存在,一个常见的选择是使析构函数为虚拟的:

struct IFooBar {
    virtual ~IFooBar() = default;
};

关于效率的说明:
就像 Java 中的 instanceof 一样,dynamic_cast 是一个非常昂贵的操作。如果此类的主要用例是过滤 CFoos 和 CBars 的列表,您可能希望在构造函数中执行此操作一次,并将它们存储在单独的容器中:

class CContainer {
public:
    CContainer(std::vector<const std::shared_ptr<IFooBar>> cPrivData) {
        for(auto const &objPtr : cPrivData)
            if(auto fooPtr = std::dynamic_pointer_cast<::CFoo>(objPtr))
                _foos.push_back(std::move(fooPtr));
            else if(auto barPtr = std::dynamic_pointer_cast<::CBar>(objPtr))
                _bars.push_back(std::move(barPtr));
    }

private:
    std::vector<const std::shared_ptr<::CFoo>> _foos;
    std::vector<const std::shared_ptr<::CBar>> _bars;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-09
    • 1970-01-01
    相关资源
    最近更新 更多