【问题标题】:How to initialize const member variable in a class?如何在类中初始化 const 成员变量?
【发布时间】:2013-01-07 20:47:21
【问题描述】:
#include <iostream>

using namespace std;
class T1
{
  const int t = 100;
  public:

  T1()
  {

    cout << "T1 constructor: " << t << endl;
  }
};

当我尝试用 100 初始化 const 成员变量 t 时。但它给了我以下错误:

test.cpp:21: error: ISO C++ forbids initialization of member ‘t’
test.cpp:21: error: making ‘t’ static

如何初始化const 值?

【问题讨论】:

标签: c++ constants


【解决方案1】:

const 变量指定变量是否可修改。每次引用变量时都将使用分配的常量值。在程序执行期间不能修改分配的值。

Bjarne Stroustrup 的 explanation 对此进行了简要总结:

一个类通常在头文件中声明,并且头文件通常包含在许多翻译单元中。但是,为了避免复杂的链接器规则,C++ 要求每个对象都有唯一的定义。如果 C++ 允许将需要作为对象存储在内存中的实体在类内定义,则该规则将被打破。

const 变量必须在类中声明,但不能在其中定义。我们需要在类外定义 const 变量。

T1() : t( 100 ){}

这里的赋值 t = 100 发生在初始化列表中,远在类初始化发生之前。

【讨论】:

  • 你能否详细说明最后一条语句Here the i = 10 assignment in initializer list happens much before the class initilizaiton occurs. 我不太明白。基本上,类中的那种允许定义是编译器特定的,对吗?
  • 我的类中有常量,我以上述方式初始化。但是,当我尝试创建该类的对象时,它给了我一个错误,说 VC++ 中的 operator = function not found。可能是什么问题?
  • 当您使用某人的确切字词而没有注明出处时,称为抄袭。请使用正确的归属 - 请参阅 stroustrup.com/bs_faq2.html#in-classstackoverflow.com/questions/13662441/…
  • 是的,我也完全不明白答案中的代码 - 那到底是什么?可以放在cpp文件实现吗?
  • 很好的解释。但值得补充的是,只有 static const int 允许在类声明本身内部初始化。
【解决方案2】:

好吧,你可以做到static

static const int t = 100;

或者你可以使用成员初始化器:

T1() : t(100)
{
    // Other constructor stuff here
}

【讨论】:

  • 为了他的使用(和/或意图),最好将其设为静态。
  • @FredLarson 是不是有些 g++ 版本不允许这种初始化?还是根本不允许?
  • @Chaitanya:C++11 非静态成员初始化器是从 gcc 4.7 实现的。
  • @MarkGarcia 为什么好多了?如果 const member 应该可以从函数/对象访问,那么它可能是必需的,那么为什么是静态的?
  • 虽然给静态初学者举个例子通常会产生误导。因为,他们可能不知道该类的所有实例(对象)只有一个。
【解决方案3】:

有几种方法可以初始化类中的 const 成员..

一般const成员的定义,也需要变量的初始化..

1) 在类内部,如果要初始化 const 语法是这样的

static const int a = 10; //at declaration

2) 第二种方式可以是

class A
{
  static const int a; //declaration
};

const int A::a = 10; //defining the static member outside the class

3) 好吧,如果你不想在声明时初始化,那么另一种方法是通过构造函数,变量需要在初始化列表中初始化(而不是在构造函数的主体中)。应该是这样的

class A
{
  const int b;
  A(int c) : b(c) {} //const member initialized in initialization list
};

【讨论】:

  • 我认为这个答案需要澄清。对类成员使用 static 关键字不会添加一些任意语法来使编译器满意。这意味着对于对象的所有实例,无论是否为常量,变量都有一个副本。这是一个需要仔细考虑的设计选择。程序员可能会决定这个常量类成员仍然会随着不同的对象而变化,尽管在给定对象的生命周期内保持不变。
  • 同意..当我们使用静态时,它只会为所有对象创建一个副本。正如您提到的那样,它是一种设计选择。在所有对象 1 和 2 的单一副本的情况下应该可以工作。如果每个对象都有单独的副本,则 3 会起作用
  • 这个答案建议进行简单的语法更改而不会产生任何后果 - 而将其更改为静态则不是。
  • 如果需要使用 double 或 float 怎么办?这是 C++11 标准的一部分吗?
【解决方案4】:

如果您不想将类中的const 数据成员设为静态,您可以使用类的构造函数初始化const 数据成员。 例如:

class Example{
      const int x;
    public:
      Example(int n);
};

Example::Example(int n):x(n){
}

如果类中有多个const 数据成员,您可以使用以下语法来初始化成员:

Example::Example(int n, int z):x(n),someOtherConstVariable(z){}

【讨论】:

  • 我认为这提供了一个比被接受的更好的答案......
  • 感谢您提供清晰的示例,以及显示复数的变体!消除了读者的歧义和额外的研究/滚动!
【解决方案5】:
  1. 您可以升级您的编译器以支持 C++11,您的代码将会完美运行。

  2. 在构造函数中使用初始化列表。

    T1() : t( 100 )
    {
    }
    

【讨论】:

    【解决方案6】:

    另一种解决方案是

    class T1
    {
        enum
        {
            t = 100
        };
    
        public:
        T1();
    };
    

    所以 t 被初始化为 100 并且它不能被改变并且它是私有的。

    【讨论】:

      【解决方案7】:

      如果一个成员是一个数组,它会比正常的有点复杂:

      class C
      {
          static const int ARRAY[10];
       public:
          C() {}
      };
      const unsigned int C::ARRAY[10] = {0,1,2,3,4,5,6,7,8,9};
      

      int* a = new int[N];
      // fill a
      
      class C {
        const std::vector<int> v;
      public:
        C():v(a, a+N) {}
      };
      

      【讨论】:

        【解决方案8】:

        另一种可能的方式是命名空间:

        #include <iostream>
        
        namespace mySpace {
           static const int T = 100; 
        }
        
        using namespace std;
        
        class T1
        {
           public:
           T1()
           {
               cout << "T1 constructor: " << mySpace::T << endl;
           }
        };
        

        缺点是其他类如果包含头文件也可以使用常量。

        【讨论】:

          【解决方案9】:

          这是正确的做法。你可以试试这段代码。

          #include <iostream>
          
          using namespace std;
          
          class T1 {
              const int t;
          
              public:
                  T1():t(100) {
                      cout << "T1 constructor: " << t << endl;
                  }
          };
          
          int main() {
              T1 obj;
              return 0;
          }
          

          如果您使用C++10 Compiler or below,那么您不能在声明时初始化 cons 成员。所以这里必须让构造函数初始化 const 数据成员。也必须使用初始化列表T1():t(100)来即时获取内存。

          【讨论】:

            【解决方案10】:

            您可以添加static 以使该类成员变量的初始化成为可能。

            static const int i = 100;
            

            但是,在类声明中使用这并不总是一个好习惯,因为从该类中实例化的所有对象都将共享相同的静态变量,该静态变量存储在实例化对象的范围内存之外的内部内存中。

            【讨论】:

              【解决方案11】:

              在 C++ 中,您不能在声明时直接初始化任何变量。 为此,我们必须使用构造函数的概念。
              看这个例子:-

              #include <iostream>
              
              using namespace std;
              
              class A
              {
                  public:
                const int x;  
                
                A():x(0) //initializing the value of x to 0
                {
                    //constructor
                }
              };
              
              int main()
              {
                  A a; //creating object
                 cout << "Value of x:- " <<a.x<<endl; 
                 
                 return 0;
              }
              

              希望对你有帮助!

              【讨论】:

                猜你喜欢
                • 2019-09-02
                • 1970-01-01
                • 1970-01-01
                • 2014-09-08
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多