C++ 成员变量的初始化顺序问题详解
成员变量的初始化顺序是每个C++程序员都必须关心的问题之一。它不仅仅会影响程序的正确性,还会影响代码的可维护性和可读性。本文将详细讲解C++成员变量的初始化顺序问题,并提供示例说明。
初始顺序规则
在C++中,成员变量的初始化顺序是有规则的。具体规则如下:
-
在构造函数中,成员变量按照声明顺序初始化。
-
如果成员变量是另一个类的对象,则该类的对象先于当前类的其他成员变量初始化。
-
如果成员变量是静态成员变量,则它们先于非静态成员变量初始化。
下面,我们将针对这三个规则进行说明和演示。
按照声明顺序初始化
成员变量按照声明的顺序初始化,这个规则非常简单直观,下面提供一个示例:
class Demo
{
public:
Demo(int a, int b, int c): m_iA(a), m_iB(b), m_iC(c) {}
private:
int m_iA;
int m_iB;
int m_iC;
};
int main()
{
Demo d(1, 2, 3);
return 0;
}
在上面的代码中,Demo类有三个int类型的成员变量,它们分别是m_iA、m_iB和m_iC,它们按照声明的顺序初始化。
对象成员按照类声明顺序初始化
如果一个成员变量是另一个类的对象,则该类的对象先于当前类的其他成员变量初始化。这个规则可能比较难理解,下面提供一个示例:
#include <iostream>
class DemoA
{
public:
DemoA(int iX): m_iX(iX)
{
std::cout << "DemoA constructor" << std::endl;
}
~DemoA()
{
std::cout << "DemoA destructor" << std::endl;
}
private:
int m_iX;
};
class DemoB
{
public:
DemoB(int iY): m_iY(iY), m_DemoA(1)
{
std::cout << "DemoB constructor" << std::endl;
}
~DemoB()
{
std::cout << "DemoB destructor" << std::endl;
}
private:
int m_iY;
DemoA m_DemoA;
};
int main()
{
DemoB b(2);
return 0;
}
在上面的代码中,DemoB类有一个int类型的成员变量m_iY和一个DemoA类型的成员变量m_DemoA。构造函数的参数iY用于将m_iY初始化为2,而m_DemoA则在构造函数内部初始化为一个iX为1的DemoA对象。
在创建DemoB对象b时,首先调用了DemoA的构造函数,然后调用DemoB自身的构造函数,初始化了m_iY和m_DemoA。
执行上述代码,输出如下:
DemoA constructor
DemoB constructor
DemoB destructor
DemoA destructor
可以看到,DemoA的构造函数被先调用,然后才是DemoB的构造函数。
静态成员变量先于非静态成员变量初始化
静态成员变量先于非静态成员变量初始化,主要是由于静态成员变量的生命周期比较特殊。下面提供一个示例:
#include <iostream>
class Demo
{
public:
Demo(std::string strName): m_strName(strName)
{
++m_iCounter;
}
void Print()
{
std::cout << "Name: " << m_strName << ", Counter: " << m_iCounter << std::endl;
}
private:
std::string m_strName;
static int m_iCounter;
};
int Demo::m_iCounter = 0;
int main()
{
Demo d1("Demo1");
d1.Print();
Demo d2("Demo2");
d2.Print();
return 0;
}
在上面的代码中,Demo类有一个std::string类型的成员变量m_strName和一个静态int类型的成员变量m_iCounter,m_iCounter用于计数当前Demo对象的个数。
在Demo的构造函数中,每创建一个Demo对象,m_iCounter就会自增1。在main函数里面,我们创建了两个Demo对象d1和d2,并打印出它们的名称和计数器值。
执行上述代码,输出如下:
Name: Demo1, Counter: 1
Name: Demo2, Counter: 2
可以看到,m_iCounter在Demo的构造函数中使用了静态成员变量,而且静态成员变量有自己的初始化顺序规则,所以m_iCounter先于m_strName被初始化。
总结
在C++中,成员变量的初始化顺序是非常重要的,因为它不仅会影响程序的正确性,还会影响代码的可维护性和可读性。在实际编写代码时,程序员需要注意遵守上述三个规则,以确保成员变量被正确初始化。如果不遵守这些规则,可能会导致程序崩溃、数据错误、难以维护的代码等问题。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++ 成员变量的初始化顺序问题详解 - Python技术站