我有一组实现接口的对象,我希望在它上面使用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<>
个对象。这是我走了多远:
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 ++中给出了als Java示例的直观可用的实现?或者,getter的推荐名称是什么?我了解到,在C ++中,getter的命名没有前导'get',函数名称从大写开始。我希望getter能够反映它返回的类类型。
也许我应该采取其他方式?而不是函数CFoo()
,我可以定义一个赋值构造函数,如果是,如何?我是否必须重载shared_ptr<>
才能这样做?如果是这样,怎么样?这样的事情是我的想法:
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'ish,但我对C ++很新。)也许这种方法很糟糕,因为也许我不能在线使用它。或者我可以吗?从上面的Java示例中,我希望能够执行container.getFoo().doSomethingFooSpecific();
之类的操作。在C ++中,我必须使用什么语法?有((CFoo)cContainer).DoSomethingFooSpecific();
之类的东西吗?如果我只使用一次,我不想要分配一个变量,如果可能的话。
答案 0 :(得分:2)
注意:此答案中的代码未经测试,可能包含拼写错误。
我了解到在C ++中,getter的命名没有前导'get',函数名称以大写字母开头。
据我所知。但正如Gill Bates所提到的,C ++没有集中式样式指南,所以只需选择代码样式并坚持下去。我个人从来没有看到以'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
是一项非常昂贵的操作。如果此类的主要用例是过滤CFoo
和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;
};