初识构造函数
构造函数的任务是初始化类对象的数据成员,无论何时只要类的对象被创建,就会执行构造函数。
一、构造函数注意
- 名字和类名相同。
- 没有返回类型。
- 有一个(可以为控)的参数列表和一个(可以为空)的函数体。
- 可以重载。
- 不能被声明为const。
- 当创建一个const对象时,知道构造函数完成初始化过程,对象才能取得常量属性。
- 在对象实例化时编译器自动调用。
二、默认构造函数
只有没有显式的定义构造函数时会提供一个默认的构造函数。
Test(); //Test是类的名字
常见使用误区:
int main()
{
Test test(); //错误,定义了一个函数而非对象
Test test; //正确,test是一个对象而非函数
}
三、初始化列表
在构造函数中,初始化对象的成员变量时,可以使用初始化列表。
而不是在构造函数体内进行赋值。
class MyClass {
private:
int x;
std::string str;
public:
MyClass(int val, const std::string& s) : x(val), str(s)
{
// 初始化列表在这里,用于初始化x和str
// 构造函数体内可以执行其他初始化或操作
}
void print() const
{
std::cout << "x: " << x << ", str: " << str << std::endl;
}
};
注意:如果成员是const、引用等类型,我们必须使用初始化列表来为这些成员提供初始值。
class Test
{
int a;
const int b;
int &c;
};
//如果使用构造函数内初始化
Test(int aa, int bb, int cc)
{
a = aa;
b = bb; //错误:const int类型不能用int类型赋值
c = cc; //错误:c未初始化
}
正确情况应该使用初始化列表
Test(int aa, int bb, int cc): a(aa), b(bb), c(cc) { }
注意:成员初始化的顺序(编译器不同,顺序不同)
class Test
{
int a;
int b;
public:
Test(int c) : b(c) ,a(b);
};
此代码看着是对的,在构造函数执行的时候,c给b赋值,b给a赋值,看起来很正常。
但是在某些编译器中,是从右往左开始初始化的,首先b给a赋值,但是b未初始化,所以这样写是非法的。
四、类外定义构造函数
class MyClass
{
private:
int x;
std::string str;
public:
// 声明构造函数
MyClass(int val, const std::string& s);
};
// 定义构造函数
MyClass::MyClass(int val, const std::string& s) : x(val), str(s)
{
}
五、委托构造函数
在C++中,其实并没有一个直接叫做 “委托构造函数” 的语言特性,但有一种常见的模式或技巧,它允许一个构造函数调用同一个类中的另一个构造函数来初始化对象。
class MyClass
{
public:
MyClass(int aa, int bb): a(aa), b(bb) { }
MyClass() : MyClass(10,20) //此处用到委托构造函数
{
cout << "MyClass() : MyClass(10,20)" << endl;
}
private:
int a;
int b;
};
int main()
{
MyClass mc;
return 0;
}
六、结构体可以有构造函数吗
在C++中,结构体和类主要区别在于成员的默认访问权限(在struct中是public,在class中是private)。从C++11开始,结构体和类都可以有构造函数、析构函数、成员函数、继承等。
因此,结构体类型可以有构造函数
。你可以像定义类一样为结构体定义构造函数。
struct MyStruct {
int x;
float y;
// 构造函数
MyStruct(int valueX, float valueY) : x(valueX), y(valueY) {}
// 其他成员函数...
};
int main() {
MyStruct s(10, 20.5f); // 使用构造函数创建MyStruct对象
return 0;
}