一、构造函数整体赋值与初始化列表赋值
1、整体赋值
class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
上面的代码为整体赋值,调用构造函数后,对象会有一个初值。但是,其只能称为赋初值****而不是初始化,因为初始化只能有一次,而构造函数体内可以多次赋值。
2、初始化列表
以冒号开始,以逗号分隔,在小括号里赋初值。
特点:
1、每个成员变量只能在初始化列表中出现一次(初始化只能有一次)
2、引用成员变量、const成员变量、没有默认构造的类类型成员变量,必须在初始化列表进行初始化。
3、不管是否使用初始化列表进行初始化,自定义类型成员变量一定会先使用初始化列表初始化,故一般定义时尽量使用初始化列表。
4、成员变量在类中声明次序就是其在初始化列表中的初始化顺序,和其在初始化列表中的先后次序无关。
3、explicit 英 [ɪkˈsplɪsɪt] 关键字
expilct修饰构造函数,将会禁止单参构造函数的隐式转换。
void TestDate() { Date d1(2018); d1 = 2019;//用2019构造了一个无名对象,将其赋值给d1, }
构造函数加了关键字explicit后,会禁止这种操作
4、必须用初始化列表初始化的几种情况:
- 类的成员变量有const修饰;
- 类的成员为引用;
- 类的成员为没有默认构造函数的类类型
4、如果类存在继承关系,派生类必须在其初始化列表中调用基类的构造函数;
二、static成员
给成员变量或成员函数加上static修饰,变为静态成员变量和静态成员函数,静态成员变量要在类外进行初始化。
class A { public: static int a; }; int A::a=0;
- 为什么静态成员变量要类外进行初始化?
1、类中只声明了,没有定义。
2、静态成员是“类级别”的,在编译阶段已经存在也就是它和类的地位等同,而普通成员是“对象(实例)级别”的。类级别的成员,先于该类任何对象的存在而存在,它被该类所有的对象共享。
3、如果在类内初始化会出现什么问题呢?
若两个线程都要创建对象,此时会发生
(1)重定义
(2)可能造成死锁问题
所以要将其在类外定义好,再进行类共享
1、特性:
- 静态成员变量
1)所有对象共享,无论谁改了静态成员变量,所有对象的一起改。
2)存储在安全区,不占用类空间,所以去sizeof的时候不算在内。
3)赋初值只能在类外,赋值时不加static,用类型 类名::变量名 = n 直接赋值- 静态成员函数
1)只能直接访问静态成员变量,无法访问其他的普通成员,因为它没有this指针
- 静态成员函数可以调用非静态成员函数?
不可以
- 非静态成员函数可以调用类的静态成员函数吗?
可以
- C++11支持非静态成员变量在定义的时候直接初始化
三、友元
友元分为友元函数和友元类
1、友元函数
1) 是一个普通外部函数和类无关。
2)输入输出运算符的重载时,可以保证类对象可以调用该函数且不妨碍输入输出运算符重载的第一个参数是ostream &out.
3)是在类内声明,在类外部定义的普通函数,声明时要加friend关键字。
2、特性:
1)友元函数可以访问类的私有成员,但不是类的成员函数
2)友元函数不可以用const修饰
3)友元函数可以在类定义的任何地方声明,不受类访问限定符限制。
4)一个函数可以是多个类的友元函数
3、友元类
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
class Date; // 前置声明
class Time
{
friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量
public:
Time(int hour, int minute, int second)
: _hour(hour)
, _minute(minute)
, _second(second)
{}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
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;
};
日期类为时间类的友元类,所以日期类可以访问友元类的私有成员变量
- 友元关系是单向的,不具有交换性。
Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。- 友元关系不能传递 如果B是A的友元,C是B的友元,则不能说明C是A的友元
四、内部类
定义在一个类内部的类称为内部类。
1、内部类是外部类的友元类,而外部类不是内部类的友元类(内部类可通过外部类的对象参数访问外部类所有成员,但外部类不可以访问内部类的所有成员)
2、内部类可以定义在外部类的任何权限的作用域
3、内部类可以直接访问外部类的static、枚举成员,不需要外部类的对象/类名
4、sizeof(外部类)=外部类,和内部类没有任何关系。
#include<iostream>
using namespace std;
class A
{
private:
static int k;
int h;
public:
class B
{
public:
void foo(const A& a)
{
cout << k << endl;//OK
cout << a.h << endl;//OK
}
};
};
int A::k = 1;
int main()
{
A a;
A::B b;
b.foo(A());
cout << sizeof(a) << endl;//4, static不算
cout<<sizeof(b)<<endl;//1
system("pause");
return 0;
}
C++是基于面向对象的程序,面向对象有三大特性即:封装、继承、多态。
封装就是将具有相同属性的东西归为一个类,通过访问限定符选择性的与外部进行交互。