【问题标题】:How do I use member functions of constant arrays in C++?如何在 C++ 中使用常量数组的成员函数?
【发布时间】:2009-10-28 19:04:09
【问题描述】:

这是我所拥有的(不工作)的简化版本:

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' 左侧必须有类/结构/联合

该错误仅在我尝试使用 c_astrExamples 的成员函数时发生。 如果我用数字 2 替换“c_astrExamples.length()”,一切似乎都正常工作。

我能够使用 c_strExample1 和 c_strExample2 的成员函数,所以我认为这种行为是由于我使用字符串与字符串数组之间存在一些差异。

我在 prog.h 中的初始化是否错误?我需要 prog.cpp 中的特殊内容吗?

【问题讨论】:

    标签: c++ arrays constants


    【解决方案1】:

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

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

    【讨论】:

    • @Grumdrig:你需要开始一个新句子:'...vector。如果你...'
    • @quamrana - Grumdrig 的句子对我来说解析正确。 “如果你想废话,你应该使用 X,否则就这样做。”完美的语法结构。
    • 我还要提醒提问者,他要小心 sizeof()。它经常让新手感到困惑,它不会告诉你编译器不知道的任何东西的大小,例如。动态分配的内存,或者作为参数传递给函数的东西。
    • 向量的问题在于,这个问题直接处理常量数组,构造一个常量向量并非易事(在C++0x中会更容易)选项范围从创建数组常量到将它们用作迭代器,或在初始化位置调用的函数中创建值。
    • 关于数组元素个数的计算:还有其他解决方案,明确搜索。虽然最初难以阅读,但如果您尝试在非数组元素(作为指针)上调用它,则有模板版本和宏会适得其反。一个简单的模板版本是:template &lt;typename T, std::size_t N&gt; inline std::size_t array_size( T (&amp;a)[N] ) { return N; },对我来说,它比所提供的解决方案更可取(如果面对的是指针而不是数组,它将很难失败)
    【解决方案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();
    

    【讨论】:

      【解决方案3】:

      C++ 中的数组继承自 C,它不是面向对象的。所以它们不是对象,也没有成员函数。 (因为它们的行为类似于intfloat 和其他内置类型。)从这个祖先开始,数组会出现更多问题,比如它们很容易(例如,当传递给函数时)衰减为指针到第一个没有大小信息的元素。

      通常的建议是改用std::vector,它是一个可动态调整大小的数组。但是,如果您在编译时知道数组大小并且您需要一个常量,那么 boost's array type (boost::array,如果您的编译器支持 TR1 标准扩展,也可以作为 std::tr1::array,在C++ 标准的下一个版本)是你想要的。

      编辑 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;}
      

      就足够了(并且更容易阅读和理解)。

      【讨论】:

      • 感谢关于衰减为指向第一个元素的指针的附加说明。这解释了我得到的一些行为,这让我相信我有一个指向数组的指针。
      • 这里的一个重要说明是模板调用上的模板 + sizeof() 将提供一个编译时间常数。还有其他更简单、更易于阅读的语法,它们是安全的,但会产生运行时值:template &lt;typename T, std::size_t N&gt; inline std::size_t array_size( T (&amp;)[N] ) { return N; } 是安全的,并且在大多数编译器中会在编译时内联并转换为常量(没有运行时开销),但它不是“编译”可用于元编程的时间常数。
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

        • 请注意,此宏的缺点是它使用array 作为指针进行编译。 (改用sizeof( 0[array] ),它会因指针而失败,但适用于数组。)
        • @sbi:0[pointer] 应该怎么失败?据我所知,这是 C++ 中的有效操作。 (就 g++ 4.0 而言)
        【解决方案6】:

        另外,请注意头文件中的初始化。您可能会冒犯链接器。
        你应该有:

        prog.h:

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

        【讨论】:

        • 对于const 对象,我认为这不是真的。
        • @sbi:你说的很对,但如果const 被删除,这也无妨。
        • @quamrana:虽然有时它确实会受伤,所以要小心:在struct X { static const int k = 5; }; 中,X::k 可以用作编译时常量(例如,用于指定堆栈数组的大小)。如果它已经在类的 cpp 文件中初始化,这是不可能的。此外,将全局常量更改为 全局变量 无论如何都应该引起一些注意。 Paul 的代码会在链接时失败可能算是一个优势。
        猜你喜欢
        • 1970-01-01
        • 2012-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-09
        • 1970-01-01
        • 2014-10-03
        • 1970-01-01
        相关资源
        最近更新 更多