如何在不取消定义类型的情况下为 C++ 中的类型编写 getter?
How to write a getter for a type in C++ without undefining the type?
我有一个实现接口的对象集合,我想在其上添加 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;
};
显然这是行不通的,我不能给 getter 起它应该有的名字(我想)。我收到指示的错误。该函数似乎未定义类型名称。现在我想知道 哪个是我在 C++ 中给出的 Java 示例的直观可用实现? 或者,getter 的推荐名称是什么?我了解到在 C++ 中,getter 的命名不带前导“get”,并且函数名称以大写开头。我希望 getter 反映 class 输入的内容 returns。
也许我应该走完全不同的路?我可以定义一个赋值构造函数而不是函数 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();
的东西?如果可能的话,如果我只使用它一次,我不想分配一个变量。
注意:此答案中的代码未经测试,可能包含拼写错误。
I learned that in C++ the getter is named without leading ‘get’, and function names start uppercase.
据我所知不是。但是正如 所提到的,C++ 没有集中的风格指南,所以只需选择一种代码风格并坚持下去。我个人从未见过在 ol'MFC 和 WINAPI 之外以大写字母开头的函数——您可能会想到 C#。 C
class 前缀同上。
在任何情况下,名称冲突都可以通过 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
, or in your case the 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
是一个相当昂贵的操作。如果此 class 的主要用例是过滤 CFoo
和 CBars
的列表,您可能希望在 once构造函数,并将它们存储在单独的容器中:
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;
};
我有一个实现接口的对象集合,我想在其上添加 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;
};
显然这是行不通的,我不能给 getter 起它应该有的名字(我想)。我收到指示的错误。该函数似乎未定义类型名称。现在我想知道 哪个是我在 C++ 中给出的 Java 示例的直观可用实现? 或者,getter 的推荐名称是什么?我了解到在 C++ 中,getter 的命名不带前导“get”,并且函数名称以大写开头。我希望 getter 反映 class 输入的内容 returns。
也许我应该走完全不同的路?我可以定义一个赋值构造函数而不是函数 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();
的东西?如果可能的话,如果我只使用它一次,我不想分配一个变量。
注意:此答案中的代码未经测试,可能包含拼写错误。
I learned that in C++ the getter is named without leading ‘get’, and function names start uppercase.
据我所知不是。但是正如 C
class 前缀同上。
在任何情况下,名称冲突都可以通过 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
, or in your case the 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
是一个相当昂贵的操作。如果此 class 的主要用例是过滤 CFoo
和 CBars
的列表,您可能希望在 once构造函数,并将它们存储在单独的容器中:
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;
};