构造函数
构造函数体中的语句只能将其称作为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。构造函数体赋值初始化;初始化列表;explicit关键字
class {
public:
A(int a = 0) //初始化列表,可缺省,缺省不是初始化
:_a(a)
{}
private:
int b = 10; //缺省,默认构造函数会用这个值初始化
int _a;
};
class B {
public:
B(int a, int ref) //初始化只能初始化一次
:_aobj(a)
, _ref(ref)
, _n(10)
{}
private: //成员变量在类中声明次序就是其在初始化列表中的初始化顺序
A _aobj; //自定义类型成员;
int& _ref; //引用;
const int _n; //const;必须在初始化列表初始化
};
explicit
对类的构造函数进行修饰。被修饰的构造函数的类,禁止隐式调用类内的单参数构造函数,只能以显示的方式进行类型转换。
(1)该关键字只能用于修饰类内部的构造函数。
(2)该关键字修饰的多参数构造函数是无效的。
(3)禁止隐式调用拷贝构造函数。
(4)禁止类对象之间的隐式转换方式。
class F {
public:
explicit f(int _data) {
data = _data;
}
private:
int data;
};
int main() {
F f(10);
return 0;
}
static成员
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态的成员变量一定要在类外进行初始化
#include<iostream>
using namespace std;
class A
{
public:
A() { ++_scount; }
A(const A& t) { ++_scount; }
static int GetACount() { return _scount; }
private:
static int _scount;
};
int A::_count = 0;
int main()
{
cout << A::GetACount() << endl;
A a1, a2;
A a3(a1);
cout << A::GetACount() << endl;
return 0;
}
- 静态成员为所有类对象所共享,不属于某个具体的实例;
- 静态成员变量必须在类外定义,定义时不添加static关键字;
- 类静态成员即可用类名::静态成员或者对象.静态成员来访问;
- 静态成员函数没有隐藏的this指针,不能访问任何非静态成员;
- 静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值;
- 静态成员函数不可以调用非静态成员函数;
- 非静态成员函数可以调用类的静态成员函数。
友元
友元函数
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。
eg. 因为cout和cin的输出输入流对象和隐含的this指针在抢占第一个参数的位置(this指针默认是第一个参数也就是左操作数了),但是实际使用中cout需要是第一个形参对象,才能正常使用。所以我们要将operator<<重载成全局函数。但是会导致类外没办法访问成员,那么就需要友元来解决。
#include<iostream>
using namespace std;
class Test {
friend ostream & operator<<(ostream &out, Test &obj);
friend istream & operator >> (istream &in, Test &obj);
public:
Test(int a = 0, int b = 0) {
this->a = a;
this->b = b;
}
void display() {
cout << "a:" << a << " b:" << b << endl;
}
private:
int a;
int b;
};
ostream & operator<<(ostream &out, Test &obj) {
out << obj.a << " " << obj.b;
return out;
}
istream & operator>>(istream &in, Test &obj) {
in >> obj.a >> obj.b;
return in;
}
int main() {
Test t1(1, 2);
cout << t1 << endl;
cin >> t1;
cout << t1 << endl;;
return 0;
}
注:
- 友元函数可访问类的私有和保护成员,但不是类的成员函数。
- 友元函数不能用const修饰。
- 友元函数可以在类定义的任何地方声明,不受类访问限定符限制。
- 一个函数可以是多个类的友元函数,它的调用与普通函数的调用和原理相同。
友元类
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。友元关系是单向的,不具有交换性且不能传递。
内部类
如果一个类定义在另一个类的内部,这个内部类就叫做内部类。注意此时这个内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去调用内部类。外部类对内部类没有任何优越的访问权限。
注意: 内部类就是外部类的友元类。注意友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
特性: 1. 内部类可以定义在外部类的public、protected、private都是可以的。
2. 注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名。
3. sizeof(外部类)=外部类,和内部类没有任何关系。
封装
C++是基于面向对象的程序,面向对象有三大特性即:封装、继承、多态。C++通过类,将一个对象的属性与行为结合在一起,使其更符合人们对于一件事物的认知,将属于该对象的所有东西打包在一起;通过访问限定符选择性的将其部分功能开放出来与其他对象进行交互,而对于对象内部的一些实现细节,外部用户不需要知道,知道了有些情况下也没用,反而增加了使用或者维护的难度,让整个事情复杂化。面向对象其实是在模拟抽象映射现实世界。