C++构造函数
1、概念和定义格式
构造函数概念:函数名和类名相同,并且没有返回值类型的函数(void也不能写)
定义格式:
class 类名
{
public:
类名(形参表)
{
}
};
注意:
a.当对象被创建时构造函数会被自动调用,用于给对象中的成员变量进行初始化,构造函数不能手动调用.
b.如果自定义类中没有自定义构造函数,那么系统会自动提供一个无参构造函数。 一旦我们自定义过构造函数,那么系统就不再提供无参构造函数(缺省的构造函数)。
c.无参构造函数未必是没有参数,而是可以用无参的形式被调用.(就是使用缺省参数)
2、构造函数中的初始化列表:
(1).初始化列表的格式:
class 类名
{
类名(形参1,形参2):成员变量1(形参1),成员变量2(形参2)
{
//函数体
}
};
注意:成员变量的初始化顺序和初始化列表中的顺序无关,而是取决于成员变量的声明顺序。下面我看一下笔试题:题目大概意思就是这样的,
class Dumy
{
private:
int m_len;
string m_str;
public:
Dumy(string str):m_str(str),m_len(m_str.length()) //先初始化m_len,此时m_str没有被初始化,所以计算的长度不正确. 语法上没有错,但语义上是有问题的。
{
cout<<m_str<<m_len<<endl;
//输出结果 //先初始化m_len,此时m_str没有被初始化,所以计算的长度不正确. 语法上没有错,但语义上是有问题的。
}
};
解决方案:
(1)交换成员变量的声明顺序(不推荐)
(2)Dumy(string str):m_str(str),m_len(str.length()){} //相当于:m_len = str.length(); m_str = str;
注意:int n = 66;
声明:在类中出现的成员变量叫做声明,声明的时候不会申请内存空间,
定义:当对象被创建时,此时成员变量需要被定义,需要分配内存空间
初始化:当构造函数被调用时,会对成员变量进行初始化。
(2). 初始化列表的必要性
a.类中包含有常量和引用型的成员变量时,必须通过构造函数和初始化列表进行显式的初始化。
b.在子类中显示的构造它的基类部分时,必须使用初始化列表.
针对a的例子.
class CInit
{
private:
const int m_id;
//常量.
int& m_age;
//引用.
public:
CInit(int num,int age):m_id(num),m_age(age){}
};
class A
{
public:
A(void)
{
cout<<"A的构造函数被调用了"<<endl;
}
};
针对b的例子.
class B
{
private:
A a;
public:
//在执行B的构造函数体语句之前,先定义b的成员变量,然后进行初始化,如果指定了初始化
//规则,那么采用指定的初始化规则进行初始化,如果没有指定规则,那么系统采用默认的初始化方式:
//普通的数据类型用0初始化
//类类型的数据则调用缺省构造函数进行初始化。
B(void)
{
cout<<"B的构造函数被调用了"<<endl;
}
};
3.支持自定义转换的构造函数
(1).格式: 目标类::目标类(const 源类& 源对象){}
(2).注意关键字explicit修饰构造函数,表示强制编译器对隐式类型转换做检查,一旦出现隐式类型转换直接报错
class Point2d;
class Point3d
{
private:
int m_x;
int m_y;
int m_z;
public:
//Point3d(int x,int y ,int z):m_x(x),m_y(y),m_z(z){}
//explicit防止进行隐式类型转换
explicit Point3d(int x,int y = 30 ,int z = 40):m_x(x),m_y(y),m_z(z){}
//支持自定义类型转换的构造函数
Point3d(const Point2d& pd);
void print()
{
cout<<"("<<m_x<<","<<m_y<<","<<m_z<<")"<<endl;
}
};
class Point2d
{
private:
int m_x;
int m_y;
public:
Point2d(int x,int y):m_x(x),m_y(y){}
int GetX(){return m_x;}
int GetY(){return m_y;}
void print()
{
cout<<"("<<m_x<<","<<m_y<<")"<<endl;
}
//声明Point3d这个类是我的友元,可以写在类中任意位置,与访控属性无关
friend class Point3d;
};
Point3d::Point3d(const Point2d& pd)
{
m_x = pd.m_x;
m_y = pd.m_y;
m_z = 0;
}