C++ 静态常量std::vector
我正在用Qt编写一个图像查看器。 我正在尝试在头文件中执行以下操作:C++ 静态常量std::vector,c++,static,constants,private-members,C++,Static,Constants,Private Members,我正在用Qt编写一个图像查看器。 我正在尝试在头文件中执行以下操作: class ImageModel { private: const static std::vector<int> mZoomLevels; } 类图像模型 { 私人: 常量静态标准::向量mZoomLevels; } 在源文件中: int zooms[] = {1,2,3,4,5,6,7,8,9,10}; const std::vector<int> mZoomLevels(zoom
class ImageModel
{
private:
const static std::vector<int> mZoomLevels;
}
类图像模型
{
私人:
常量静态标准::向量mZoomLevels;
}
在源文件中:
int zooms[] = {1,2,3,4,5,6,7,8,9,10};
const std::vector<int> mZoomLevels(zooms.begin(),zooms.end());
int缩放[]={1,2,3,4,5,6,7,8,9,10};
const std::vector mZoomLevels(zooms.begin(),zooms.end());
但是,我得到以下错误:
在非类类型“int[10]”的缩放中请求成员“begin”
在非类类型“int[10]”的缩放中请求成员“end”
有人知道如何初始化这个静态常量私有成员吗?普通数组没有成员函数。我相信你在寻找这个:
int zooms[] = {1,2,3,4,5,6,7,8,9,10};
const std::vector ImageModel::mZoomLevels(zooms, zooms + 10);
数组没有
begin
和end
成员。您可以将数组名用于开始
,将数组名加上长度用于结束:
const std::vector mZoomLevels(zooms, zooms+10);
在C++11中,您可以使用和,如下所示:
const std::vector mZoomLevels(std::begin(zooms), std::end(zooms));
在这两种情况下,最好将
缩放数组文件声明为静态或将其隐藏在命名空间中,以确保其名称不会“污染”全局命名空间。缩放是一个没有成员和方法的C样式数组,即缩放.begin
和缩放.end
没有意义。如果使用C++ 11兼容编译器,请尝试<代码> STD::开始(ZOMS)和 STD::(ZoOM)< /C> < /P> < P>普通C++数组不能有成员。然而,您正在寻找静态分派,这可以通过参数类型进行重载解析。因此C++11提供了std::begin
和std::end
非成员函数。(这一点已经提到。)
按照以下方式习惯调用非成员函数的最佳实践(在编写通用模板代码时确实很有帮助):
无论容器缩放的是什么类型,这都将正常工作,并且如果缩放的具有某种自定义类类型,它将利用ADL(参数相关查找,有时称为Koenig查找)在同一命名空间中查找开始
和结束
的实现
顺便说一句,std::begin
和std::end
是由C++11提供的,但是对于早期版本,您可以轻松编写自己的:
template <typename T, size_t N>
T* begin( T (&a)[N] ) { return a; }
template <typename T, size_t N>
T* end( T (&a)[N] ) { return a + N; }
模板
T*begin(T(&a)[N]){returna;}
模板
T*end(T(&a)[N]){返回a+N;}
根据您是否有权访问C++11,我将采用不同的方法
在C++03中,我将使用普通数组(因为它是常量),甚至可能不在类中,而是在实现文件中的私有名称空间中(因为它是私有的,假设只有一个转换单元具有ImageModel
的成员定义)
如果您真的想继续使用std::vector
方法,我会在翻译单元中创建一个定义成员的助手函数,并使用该函数创建std::vector
,而不创建具有静态持续时间的其他变量:
namespace {
static std::vector<int> chooseANameForInitializer() {
int data[] = { 1, 2, 3 };
return std::vector<int>( data, data + (sizeof data/sizeof *data) );
}
}
const std::vector<int> ImageModel::mZoomLevels = chooseANameForInitializer();
名称空间{
静态std::vector chooseANameForInitializer(){
int data[]={1,2,3};
返回std::vector(数据,数据+(sizeof data/sizeof*data));
}
}
常量std::vector ImageModel::mZoomLevel=chooseANameForInitializer();
在C++11中,我将使用std::array
,因为这样可以避免动态分配和额外间接寻址的开销。虽然这不是一个很大的收获,但是当您不需要它提供的任何功能时,拥有一个std::vector
是没有意义的
class ImageModel
{
private:
static const std::array<int,10> mZoomLevels;
};
// cpp:
const std::array<int,10> ImageModel::mZoomLevels = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
类图像模型
{
私人:
静态常量std::数组mZoomLevels;
};
//cpp:
常量std::array ImageModel::mZoomLevel={1,2,3,4,5,6,7,8,9};
同样,如果您坚持使用std::vector
,则可以使用列表初始化
const std::vector ImageModel::mZoomLevels{1,2,3,4,5,6,7,8,9};
为什么使用?这里不需要ADL。@DeadMG:为什么不使用?如果他养成了正确操作的习惯,在模板中使用它时不会突然出现问题。模板不会改变任何东西。他在本机数组上调用它-std::begin
和std::end
将始终被选中。@DeadMG:想想这样的情况,zooms
是一个参数,而不是全局变量,参数类型被模板化以允许任何容器类型。问题中的代码是SSCE,不一定像可能遇到的实际情况那样复杂。@DeadMG:当不需要ADL时,为什么使用?using指令将符号引入范围,该符号几乎与ADL正交。。。如果您想要ADL支持,当然需要它,但这不是使用声明的唯一目的。应该是const std::vector ImageModel::mZoomLevels(…)
?谢谢您的快速回答!如果您有C++11并且想要初始化向量,则无需创建数组,只需使用列表初始化:const std::vector ImageModel::mZoomLevels{1,2,3,4…}代码>--代码越少,就可以删除不需要的数组。如果您真的想使用std::vector
。。。我不太确定。。。
namespace {
static std::vector<int> chooseANameForInitializer() {
int data[] = { 1, 2, 3 };
return std::vector<int>( data, data + (sizeof data/sizeof *data) );
}
}
const std::vector<int> ImageModel::mZoomLevels = chooseANameForInitializer();
class ImageModel
{
private:
static const std::array<int,10> mZoomLevels;
};
// cpp:
const std::array<int,10> ImageModel::mZoomLevels = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const std::vector<int> ImageModel::mZoomLevels{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };