目录
初始化列表
当我们对象定义的时候会自动调用构造函数完成初始化,但是由于类中的成员变量只是声明,那么成员变量在什么时候定义并初始化呢?初始化列表就是给成员变量依次定义处理的地方,当到构造函数体内的时候,成员变量就已经定义好了。
而有些变量定义的时候可以不初始化,计算机给一个随机值,但是有些变量必须在定义的时候初始话,如const、引用、没有默认构造函数的自定义成员变量。
class A
{
public:
A(int a) //带参数,不是默认构造函数
{
_a = a;
}
private:
int _a;
};
class Date
{
public:
Date(int year, int month, int day, int i)
:_N(10) //初始化列表,成员变量定义的地方
, _ref(i)
, _aa(-1)
{
//到构造函数体内,成员变量已经定义出来了
_year = year;
_month = month;
_day = day;
}
private:
int _year; //声明
int _month;
int _day;
const int _N; //const
int& _ref; //引用
A _aa; //没有默认构造函数的自定义类型成员变量
}; //他们必须在定义的时候初始化
int main()
{
int i = 0;
Date d1(2001, 1, 15, i); //对象定义/对象实例化
//int j;
//const int g = 0; //常量必须在定义的时候初始化
return 0;
}
那么自定义类型成员变量不在初始话列表初始化应该怎么写呢?
class A
{
public:
A(int a = 0)
{
cout << "A(int a = 0)" << endl;
_a = a;
}
A(const A& aa)
{
cout << "A(const A& aa)" << endl;
_a = aa._a;
}
A& operator=(const A& aa)
{
cout << "A& operator=(const A& aa)" << endl;
_a = aa._a;
return *this;
}
private:
int _a;
};
class Date
{
public:
//不用初始化列表初始化
Date(int year, int month, int day, const A& aa)
{
_aa = aa;
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
A _aa;
};
int main()
{
/*A aa(10);
Date d1(2009, 9, 1, aa);*/
Date d1(2009, 9, 1, A(10));
return 0;
}
我们可以清楚得看到,不用初始化列表会调用很多构造函数,因此,推荐使用初始化列表初始化。
即使我们不写初始化列表,自定义类型成员变量也会在那自动调用它的默认构造函数初始化。并且,先声明的先初始化。
explicit
explicit,阻止隐式类型转化。
class Date
{
public:
Date(int year)
:_year(year)
{
cout << "Date(int year)" << endl;
}
/*explicit Date(int year)
:_year(year)
{
cout << "Date(int year)" << endl;
}*/
Date(const Date& dd)
{
cout << "Date(Date& dd)" << endl;
}
private:
int _year;
};
int main()
{
Date d1(2022);
Date d2 = 2022; //隐式类型转换
//用2022构造一个临时对象Date(2022), 再用这个对象拷贝构造d2
//编译器在连续的一个过程中,多个构造会被优化,合二为一
return 0;
}
静态的成员变量与成员函数
成员变量和成员函数都有可能是静态的,静态的成员变量属于整个类,所有对象,生命周期是整个程序运行期间,类成员函数中可以随便访问,必须在类外面全局完整完成定义和初始化。静态的成员函数没有this指针,只能访问静态的成员变量和成员函数。
class A
{
public:
A(int a = 0)
:_a(a)
{
++_sCount;
}
A(const A& aa)
:_a(aa._a)
{
++_sCount;
}
//没有this指针,只能访问静态成员变量和成员函数
static int GetCount()
{
return _sCount;
}
private:
int _a;
//静态成员变量属于整个类,所有对象,生命周期在整个程序运行期间
//类成员函数中,可以随便访问
static int _sCount; //声明
};
int A::_sCount = 0; //定义初始化
void f(A a)
{}
int main()
{
A a1;
A a2 = 1;
f(a1);
cout << a1.GetCount() << endl;
cout << A::GetCount() << endl;
return 0;
}
C++11的新语法,外面可以在成员变量声明的时候给一个缺省值。
class B
{
public:
B(int b=0)
:_b(b)
{}
private:
int _b;
};
class A
{
public:
A()
{}
private:
int _a1 = 0;
int _bb1 = 10;
B _bb2 = B(20);
int* p = (int*)malloc(4);
//int arr[10] = { 1, 2, 3, 4, 5, 6 }; //vs2019支持
//静态的必须在类外面全局位置定义初始化
//static int _sCount = 0;
};
int main()
{
A aa;
return 0;
}
友元
友元,友元提供了一种突破类域的方式,破环了封装性,能不用尽量不用。友元分为,友元函数与友元类。
class Time
{
friend class Date; //声明Date是Time的友元类,
//在Date类中可以直接访问Time中私有成员变量
public:
Time(int hour = 0, int minute = 0, int second = 0)
:_hour(hour)
, _minute(minute)
, _second(second)
{}
void f(Date d);
private:
int _hour;
int _minute;
int _second;
};
class Date
{
friend class Time;
public:
Date(int year = 1900, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{
_t._hour = 0;
_t._minute = 0;
_t._second = 0;
}
void SetTimeOfDate(int hour, int minute, int second)
{
_t._hour = hour;
_t._minute = minute;
_t._second = second;
}
private:
int _year;
int _month;
int _day;
Time _t;
};
内部类:
class A
{
private:
static int k;
int h;
public:
//内部类
//内部类B和在全局定义基本一样,只是受A类域的限制
//B是A的友元
class B
{
//friend class A;
public:
void foo(const A& a)
{
cout << k << endl;
cout << a.h << endl;
}
private:
int _b;
};
};
int A::k = 1;
int main()
{
cout << sizeof(A) << endl;
/*A aa;
A::B bb;*/
return 0;
}