2009-10-28 106 views
0

这里是我有什么(不工作)的简化版本:如何在C++中使用常量数组的成员函数?

prog.h:

... 
const string c_strExample1 = "ex1"; 
const string c_strExample2 = "ex2"; 
const string c_astrExamples[] = {c_strExample1, c_strExample2}; 
... 

prog.cpp:

... 
int main() 
{ 
    int nLength = c_astrExamples.length(); 
    for (int i = 0; i < nLength; i++) 
     cout << c_astrExamples[i] << "\n"; 
    return 0; 
} 
... 

当我尝试建立,我得到以下错误: 错误C2228:'.length'的左边必须有class/struct/union

只有当我尝试使用成员func c_astrExamples的部分。 如果我用数字2替换“c_astrExamples.length()”,一切似乎都正常工作。

我能够使用c_strExample1和c_strExample2的成员函数,所以我认为行为出现在我使用字符串与字符串数组之间的一些区别。

我在prog.h中的初始化是否错误?我需要prog.cpp中特别的东西吗?

回答

6

C++中的数组没有成员函数。如果你想要一个对象,你应该使用像vector<string>集合,或计算这样的长度:

int nLength = sizeof(c_astrExamples)/sizeof(c_astrExamples[0]); 
+0

@Grumdrig:你需要开始一个新的句子:” .. .vector 。如果你......' – quamrana 2009-10-28 19:12:39

+4

@quamrana - Grumdrig的句子正确解析我。 “如果你想要,你应该使用X,否则就这样做。”完美的语法结构。 – asveikau 2009-10-28 19:15:41

+1

我还会注意到提问者比他小心sizeof()。它经常混淆新手,它不会告诉你编译器不知道的任何东西的大小,例如。动态分配的内存,或作为参数传递给函数的东西。 – asveikau 2009-10-28 19:21:03

0

c_astrExamples是一个数组,其中没有“length()”方法。

2

数组在C++是由C,这是不是面向对象的继承。所以它们不是对象,也没有成员函数。 (因为它们的行为类似于int,float和其他内置类型)。从该血统中解决了数组的更多问题,例如它们很容易(例如,当传入函数时)衰减为指向第一个元素的指针没有大小信息。

通常的建议是使用std::vector来代替,这是一个动态调整大小的数组。但是,如果数组大小在编译时已知,并且您需要一个常量,那么boost's array typeboost::array,如果您的编译器支持TR1标准扩展也可以使用std::tr1::array,在下一版本的C++标准中变为std::array)是你想要什么。

编辑1

一种安全的方式来获得C中的数组的长度++涉及扔进组合的模板,函数指针,甚至宏不可思议的组合:

template <typename T, std::size_t N> 
char (&array_size_helper(T (&)[N]))[N]; 

#define ARRAY_SIZE(Array_) (sizeof(array_size_helper(Array_))) 

如果你(像我一样)认为这很搞笑,看看boost::array

编辑2

由于dribeas在评论说,如果你不需要编译时间常数,这

template <typename T, std::size_t N> 
inline std::size_t array_size(T(&)[N]) 
{return N;} 

是足够了(更容易阅读和理解)。

+0

感谢关于衰减到指向第一个元素的指针的附加注释。 这解释了我得到的那一刻的行为,让我相信我有一个指向数组的指针。 – 2009-10-28 19:16:29

+2

这里的一个重要注意事项是模板调用中的template + sizeof()将提供编译时间常量。还有其他更简单,更易读的语法,它们是安全的,但会产生一个运行时值:'template inline std :: size_t array_size(T(&)[N]){return N; }'是安全的,大多数编译器都会在编译时被内联和翻译成常量(没有运行时开销),但它不是一个可以在元编程中使用的“编译时常量”。 – 2009-10-28 21:40:54

0

在C++数组中不是对象,也没有任何方法。如果您需要获取阵列的长度,您可以使用以下宏:

#define COUNTOF(array) (sizeof(array)/sizeof(array[0])) 
int nLength = COUNTOF(c_astrExamples); 
+0

请注意,这个宏的缺点是它使用'array'作为指针进行编译。 (尝试'sizeof(0 [array])',而不是指针,但是与数组一起工作。) – sbi 2009-10-28 19:20:30

+0

@sbi:'0 [指针]'应该怎么失败?就我所知,这在C++中是一个有效的操作。 (至于g ++ 4.0认为) – 2009-10-28 21:38:00

+0

@dribeas:我认为你是对的。所以从头开始。 ':('' – sbi 2009-10-28 22:17:38

-1

此外,请注意头文件中的初始化。您有冒犯冒犯链接器的风险。
你应该有:

prog.h:

extern const string c_strExample1; 
extern const string c_strExample2; 
extern const string c_astrExamples[]; 
+0

对于'const'对象,我认为这不是真的。 – sbi 2009-10-28 19:16:06

+0

@sbi:你说得很对,但它并没有伤害,以防'const'被删除。 – quamrana 2009-10-28 19:28:10

+0

@quamrana :有时它会受到伤害,所以要小心:在'struct X {static const int k = 5;};'中,''X :: k''可以用作编译时常量(例如,用于指定堆栈数组如果它已经在类的cpp文件中被初始化了,那么这是不可能的,而且,一个全局常量变成一个_global变量_应该引起一些问题,那么Paul的代码在链接 - 时间可能被认为是一个优势。 – sbi 2009-10-29 09:34:22

2

只需使用字符串代替STL vector数组:

#include <string> 
#include <vector> 
using namespace std; 

const string c_strExample1 = "ex1"; 
const string c_strExample2 = "ex2"; 
vector<string> c_astrExamples; 
c_astrExamples.push_back(c_strExample1); 
c_astrExamples.push_back(c_strExample2); 

int main() 
{ 
    int nLength = c_astrExamples.size(); 
相关问题