在规划我的程序时,我经常从一连串的想法开始:
足球队只是一个足球运动员名单.因此,我应该代表它:
Run Code Online (Sandbox Code Playgroud)var football_team = new List<FootballPlayer>();此列表的顺序表示球员在名单中列出的顺序.
但我后来才意识到,除了仅仅是球员名单之外,球队还有其他属性,必须记录下来.例如,本赛季的总得分,当前预算,统一颜色,string代表球队名称等等.
那么我认为:
好吧,足球队就像一个球员名单,但另外,它有一个名称(a
string)和一个总分(aint)..NET不提供用于存储足球队的类,所以我将创建自己的类.最相似和相关的现有结构是List<FootballPlayer>,所以我将继承它:Run Code Online (Sandbox Code Playgroud)class FootballTeam : List<FootballPlayer> { public string TeamName; public int RunningTotal }
但事实证明,指南说你不应该继承List<T>.我在两个方面完全被这个指南搞糊涂了.
显然List是以某种方式针对性能进行了优化.怎么会这样?如果我延长会给我带来什么性能问题List?究竟会打破什么?
我看到的另一个原因List是微软提供的,我无法控制它,所以我在以后暴露"公共API"后无法改变它.但我很难理解这一点.什么是公共API,我为什么要关心?如果我当前的项目没有并且不太可能拥有此公共API,我可以放心地忽略此指南吗?如果我继承List 并且事实证明我需要一个公共API,那么我将遇到什么困难?
为什么它甚至重要?列表是一个列表.什么可能改变?我可能想要改变什么?
最后,如果微软不想让我继承List,他们为什么不上课sealed呢?
显然,对于自定义集合,Microsoft提供了一个Collection应该扩展的类而不是List.但这个类是非常裸露,并没有多少有用的东西,比如AddRange,例如.jvitor83的答案提供了该特定方法的性能原理,但是如何缓慢AddRange而不是没有AddRange?
继承Collection是比继承更多的工作List,我认为没有任何好处.当然微软不会告诉我无缘无故地做额外的工作,所以我不禁觉得我在某种程度上误解了某些东西,而继承Collection实际上并不是解决我问题的正确方法.
我见过如实施的建议IList …
我经常在Stack Overflow上阅读这些语句.就个人而言,我没有发现任何问题,除非我以多态方式使用它; 即我必须使用virtual析构函数.
如果我想扩展/添加标准容器的功能那么什么是比继承一个更好的方法?将这些容器包装在自定义类中需要更多的努力并且仍然是不洁净的.
所以我一直在使用从std :: vector派生的容器.也许这是一个糟糕的设计决定,原因有几个,而且你是否应该做这样的事情的问题在这里有广泛的讨论:
我确信我已经错过了一些讨论......但是在链接中找到了两个观点的合理论据.据我所知,"因为~vector()是非虚拟的"是你不应该从stl容器继承的"规则"的基础.但是,如果我在g ++ 4.9.2中查看std :: vector的实现,我发现std :: vector继承自_Vector_base,而_Vector_base是非虚拟析构函数.
template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class vector : protected _Vector_base<_Tp, _Alloc>
{
...
~vector() _GLIBCXX_NOEXCEPT
{ std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator()); }
...
}
Run Code Online (Sandbox Code Playgroud)
哪里:
template<typename _Tp, typename _Alloc>
struct _Vector_base
{
...
~_Vector_base() _GLIBCXX_NOEXCEPT
{ _M_deallocate(this->_M_impl._M_start, this->_M_impl._M_end_of_storage
- this->_M_impl._M_start); }
...
}
Run Code Online (Sandbox Code Playgroud)
所以std :: vector的gcc 4.9.2实现继承自带有非虚析构函数的基类.这让我相信这是一种可接受的做法.为什么这样好?这种做法没有危险的具体条件是什么?
自从我上次使用c ++以来,从java和python回来已经有很长一段时间了,我对c ++的良好实践提出了疑问:
我想保留一些关于一些非常简单的对象的语义代码,假设我们有对象Tag和File,它们都只是std :: string和一个TagManager类,它包含使用Tags和Files的几个函数.
我的问题是,创建一个代表这些琐碎对象的自定义类型或直接使用它们是不是更好?
更具体地说,我可以为函数定义其中一个定义:
TagIterable myFunction(Tag tag, File file);
std::vector<Tag> myFunction(Tag tag, File file);
std::vector<std::string> myFunction(std::string tag, std::string file);
Run Code Online (Sandbox Code Playgroud)
我更喜欢第一种解决方案,因为我喜欢保留语义代码,另一方面,它需要用户检查这些类型是什么,因此它降低了使用的简单性.
我还读到另一个问题(你不能继承std :: vector)'不要生产新的实体只是为了让事情看起来更好.'
那么你在这种情况下做了什么; C++哲学建议做什么?
我尝试用SWIG生成java代码
在MyList.h中,我声明了一个名为_list的自定义列表对象
List<T*> _list;
Run Code Online (Sandbox Code Playgroud)
这个List类继承自vector
class List : public vector<T>
Run Code Online (Sandbox Code Playgroud)
在业务类中(在C++中),我返回一个自定义对象列表
List<MyObject> getMyList(){
....
return list;
}
Run Code Online (Sandbox Code Playgroud)
所以我想生成java代码,我可以在这里检索这个C++ List作为java.util.List或java.util.Vector.
在我的swig.i文件中,我无法管理如何体现
%typemap(jstype) List "java.util.Vector"
namespace std {
%template(CustomVector) vector<MyObject>;
}
Run Code Online (Sandbox Code Playgroud)
任何种类的帮助如何配置此swig.i模板文件或一些示例代码生成java.util.List/Vector返回函数将不胜感激.
谢谢.
在此之前:我不是开发人员,我可能不理解你的一些消息,因为英语不是我的母语,我的问题可能很难理解.
考虑:
class MyVector
{
std::vector<command> vec;
std::mutex vector_m;
public:
void MVpush_back(command t)
{
this->vector_m.lock();
this->vec.push_back(t);
this->vector_m.unlock();
}
};
Run Code Online (Sandbox Code Playgroud)
command 是一个自定义类(它的内容在这里似乎不相关;复制构造函数确实存在).
基本上,因为我有很多可能的作家和读者,所以我想强制使用mutex访问vec参数.
由于我只使用push_back(),erase()而且find() 我可以重新定义它们,但我不知道是否有一种方法不必重新定义的所有功能.
就像是:
<template> safe(*function name*<template>)
{
this->vector_m.lock();
<template> retval = vec.*function name*<parameter>;
this->vector_m.unlock();
return retval;
}
Run Code Online (Sandbox Code Playgroud)
调用函数的地方是一种参数......
我认为它可以使用,std::initializer_list<type>但类型要求是阻止.
有没有办法做这样的事情?
重新提问:有没有办法用参数(1)作为函数(2)的参数来推动函数,并使函数(2)调用函数(1)?
我想制作一个管理大对象的容器,它可以在复制构造和复制分配上执行深层复制.
template <class TBigObject>
class Container : public std::vector< std::shared_ptr<TBigObject> >
{
public:
Container(int nToAllocate){ /* fill with default constructed TBigObjects */ }
Container(const Container& other){ /* deep copy */ }
Container(Container&&) = default;
Container& operator = (const Container& population){ /* deep copy */ }
Container& operator = (Container&&) = default;
};
Run Code Online (Sandbox Code Playgroud)
我想知道违约是什么:
Container(Container&&) = default;
Container& operator = (Container&&) = default;
Run Code Online (Sandbox Code Playgroud)
成员实际上做了.
如果我打电话:
Container<int> makeContainer()
{
...
}
Run Code Online (Sandbox Code Playgroud)
并在以下位置设置调试断点:
Container<int> moveAssigned;
moveAssigned = makeContainer(); // EDIT corrected thanks to …Run Code Online (Sandbox Code Playgroud) 我想创建一个shared_ptr内容比较函子来代替std::less<T>关联容器和std算法.我已经看到了几个使用以下(或类似)模型的自定义比较器示例:
template <typename T>
struct SharedPtrContentsLess {
bool operator()(const boost::shared_ptr<T>& lhs,
const boost::shared_ptr<T> rhs) const {
return std::less<T>(*lhs, *rhs);
//or: return (*lhs) < (*rhs);
}
//defining these here instead of using std::binary_functor (C++11 deprecated)
typedef boost::shared_ptr<T> first_argument_type;
typedef boost::shared_ptr<T> second_argument_type;
typedef bool return_type;
};
Run Code Online (Sandbox Code Playgroud)
但为什么我不想延伸std::less呢?像这样:
template <typename T>
struct SharedPtrContentsLess : public std::less< boost:shared_ptr<T> > {
bool operator()(const boost::shared_ptr<T>& lhs,
const boost::shared_ptr<T> rhs) const {
return std::less<T>(*lhs, *rhs);
}
};
Run Code Online (Sandbox Code Playgroud)
这给我买了什么吗?
我认为这会让我typedef免费获得s,就好像我正在扩展已弃用的那样std::binary_function.在C++ …
我想std::vector<std::variant>通过索引访问成员。考虑以下片段:
struct Data {
using data_types = std::variant<std::basic_string<char>, double, int>;
public:
template <class T>
void push_back(const T& t) {
m_data.push_back(t);
}
private:
std::vector<data_types> m_data;
};
int main()
{
Data d;
d.push_back(0);
d.push_back("string");
d.push_back(3.55);
}
Run Code Online (Sandbox Code Playgroud)
我想访问诸如d[0](should return int) 或d[1](should return std::string) 之类的值。
到目前为止我已经尝试过但不起作用的是将以下公共方法添加到现有结构中:
template <class T>
T& operator[](const size_t &index) {
return std::visit([](const T& value) {
return static_cast<T>(value);
}, m_data[index]);
}
Run Code Online (Sandbox Code Playgroud)
有什么想法如何达到预期的结果吗?