做视频网站需要多大的带宽,免费个人简历表,如何自学网站建设书籍,做asp网站教程朋友们、伙计们#xff0c;我们又见面了#xff0c;本期来给大家解读一下有关Linux的基础知识点#xff0c;如果看完之后对你有一定的启发#xff0c;那么请留下你的三连#xff0c;祝大家心想事成#xff01; C 语 言 专 栏#xff1a;C语言#xff1a;从入门到精通 数… 朋友们、伙计们我们又见面了本期来给大家解读一下有关Linux的基础知识点如果看完之后对你有一定的启发那么请留下你的三连祝大家心想事成 C 语 言 专 栏C语言从入门到精通 数据结构专栏数据结构 个 人 主 页 stackY、 C 专 栏 C Linux 专 栏 Linux 目录 引言
1. 初始化列表
1.1 构造函数体赋值
1.2 初始化列表
1.3 explicit关键字
2. static成员
2.1 概念
2.2 特性
3. 友元
3.1 友元函数
3.2 友元类
4. 内部类
5. 匿名对象
6. 拷贝对象时编译器做出的优化 引言 本期我们继续承接上篇的类和对象2继续对类和对象进行收尾工作在前面我们首先对类和对象做了基本介绍以及深入了解然后自己实现了一个日期类关于类和对象还有遗留的知识点本期再来进行介绍。 1. 初始化列表
1.1 构造函数体赋值 在创建对象时编译器通过调用构造函数给对象中各个成员变量一个合适的初始值。 class Date
{
public:Date(int year, int month, int day){_year year;_month month;_day day;}
private:int _year; //年int _month; //月int _day; //日
}; 虽然上述构造函数调用之后对象中已经有了一个初始值但是不能将其称为对对象中成员变量的初始化构造函数体中的语句只能将其称为赋初值而不能称作初始化。因为初始化只能初始化一次而构造函数体内可以多次赋值。 1.2 初始化列表 初始化列表以一个冒号开始接着是一个以逗号分隔的数据成员列表每个成员变量后面跟一个放在括号中的初始值或表达式。 class Date
{
public:Date(int year, int month, int day):_year(year), _month(month), _day(day){}
private:int _year; //年int _month; //月int _day; //日
}; 【注意】 1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次) 2. 类中包含以下成员必须放在初始化列表位置进行初始化 引用成员变量const成员变量自定义类型成员(且该类没有默认构造函数时) class A
{
public:A(int a):_a(a){}
private: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
}; 3. 尽量使用初始化列表初始化因为不管你是否使用初始化列表对于自定义类型成员变量一定会先使用初始化列表初始化。 class Time
{
public:Time(int hour 0):_hour(hour){cout Time() endl;}
private:int _hour;
};class Date
{
public:Date(int day){}
private:int _day;Time _t;
};int main()
{Date d(1);return 0;
} 4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序与其在初始化列表中的先后次序无关。 class A
{
public:A(int a1, int a2, int a3) //根据声明的次序来进行初始化:_a1(a1) //2,_a2(a2) //1,_a3(a3) //3{}
private:int _a2;int _a1;int _a3;
};int main()
{A a(1, 2, 3);return 0;
} 总结 不管写不写初始化列表每一个成员都要走初始化列表内置类型用随机值处理自定义类型去调用去调用它的默认构造C11支持在声明时给缺省值这个值给初始化列表。 初始化列表使用场景 1. 必须在定义时初始化的量 2. const修饰的常变量 3. 引用值 4. 自定义类型成员且无默认构造 1.3 explicit关键字 构造函数不仅可以构造初始化对象对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数还具有类型转换的作用。 class A
{
public:A(int i)//explicit A(int i) //加上explicit可以阻止这种隐式类型的转化:_a(i){cout A(int i) endl;}A(const A aa):_a(aa._a){cout A(const A aa) endl;}~A(){cout ~A() endl;}
private:int _a;
};int main()
{A a1(1);A a2 2; //从int转化为A是一种隐式类型转化// 用2调用A构造函数生成一个临时对象再用这个对象去拷贝构造a2// 编译器会再优化优化用2直接构造const A ra 2; //类型转化会产生临时变量而临时变量具有常性需要使用const修饰return 0;
} 用explicit修饰构造函数将会禁止构造函数的隐式转换。 2. static成员
2.1 概念 声明为static的类成员称为类的静态成员用static修饰的成员变量称之为静态成员变量用static修饰的成员函数称之为静态成员函数。静态成员变量一定要在类外进行初始化 2.2 特性 1. 静态成员为所有类对象所共享不属于某个具体的对象存放在静态区 2. 静态成员变量必须在类外定义定义时不添加static关键字类中只是声明 3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问 4. 静态成员函数没有隐藏的this指针不能访问任何非静态成员 5. 静态成员也是类的成员受public、protected、private 访问限定符的限制 //统计累计创建了多少个对象
class A
{
public:A() { _scount;_scountCount;}A(const A t) { _scount; _scountCount;}~A() { --_scount; }static int GetA_scount(){ return _scount; }static int GetA_scountCount(){return _scountCount;}
private://声明static int _scount; //正在使用的对象static int _scountCount; //累计创建的对象
};
//定义
int A::_scount 0;
int A::_scountCount;A Func(A aa)
{return aa;
}int main()
{A a1, a2; //创建两个对象Func(a2); //拷贝构造时创建一个返回值又创建一个cout A::GetA_scount() endl;cout A::GetA_scountCount() endl;return 0;
}
3. 友元 友元提供了一种突破封装的方式有时提供了便利。但是友元会增加耦合度破坏了封装所以友元不宜多用。 友元分为友元函数和友元类 3.1 友元函数 友元函数可以直接访问类的私有成员它是定义在类外部的普通函数不属于任何类但需要在类的内部声明声明时需要加friend关键字。 class Date
{//友元函数friend ostream operator(ostream out, const Date d);friend istream operator(istream in, Date d);public:Date(int year 1900, int month 1, int day 1):_year(year),_month(month),_day(day){}
private:int _year;int _month;int _day;
};ostream operator(ostream out, const Date d)
{out d._year / d._month / d._day endl;return out;
}
istream operator(istream in, Date d)
{in d._year d._month d._day;return in;
}
int main()
{Date d1;cin d1;cout d1;return 0;
} 说明 友元函数可访问类的私有和保护成员但不是类的成员函数友元函数不能用const修饰友元函数可以在类定义的任何地方声明不受类访问限定符限制一个函数可以是多个类的友元函数友元函数的调用与普通函数的调用原理相同 3.2 友元类 友元类的所有成员函数都可以是另一个类的友元函数都可以访问另一个类中的非公有成员。 友元关系是单向的不具有交换性。比如上述Time类和Date类在Time类中声明Date类为其友元类那么可以在Date类中直接访问Time类的私有成员变量但想在Time类中访问Date类中私有的成员变量则不行。友元关系不能传递如果C是B的友元 B是A的友元则不能说明C时A的友元。友元关系不能继承后续解析 class Time
{friend class Date; // 声明日期类为时间类的友元类则在日期类中就直接访问Time类中的私有成员变量
public:Time(int hour 0, int minute 0, int second 0): _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;
};
4. 内部类 概念如果一个类定义在另一个类的内部这个内部类就叫做内部类。内部类是一个独立的类它不属于外部类更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。 注意内部类就是外部类的友元类内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。特性 1. 内部类可以定义在外部类的public、protected、private都是可以的。2. 注意内部类可以直接访问外部类中的static成员不需要外部类的对象/类名。3. sizeof(外部类)外部类和内部类没有任何关系。 // 1、B类受A类域和访问限定符的限制其实他们是两个独立的类
// 2、内部类默认就是外部类的友元类
class A
{
public:class B // B天生就是A的友元{public:void print(const A a){cout k endl; //可以直接访问A的静态成员变量cout a.h endl; //也可以访问A的成员变量}};
private:static int k;int h;
};
int A::k 1;int main()
{A::B b;b.print(A());cout sizeof(A) endl; //外部类的大小与内部类无关return 0;
} 5. 匿名对象 匿名对象的特点就是不用取名字生命周期只存在定义的这一行。 class A
{
public:A(int a 0):_a(a){cout A(int a) endl;}~A(){cout ~A() endl;}
private:int _a;
};int main()
{A aa1;//A aa1();// 不能这么定义对象因为编译器无法识别下面是一个函数声明还是对象定义// 但是我们可以这么定义匿名对象匿名对象的特点不用取名字A();// 但是他的生命周期只有这一行紧接着它的下一步就会自动调用析构函数A aa2(2);return 0;
} 应用场景 当我们做C的OJ题时会发现都是将其封装在一个Solution类中的假设我们需要调用这个类中的某一个函数是需要先创建一个Solution的对象然后通过这个对象进行调用这样的话有点麻烦我们可以直接使用匿名对象来调用这个类中的成员函数。 class Solution {
public:int Sum_Solution(int n) {//...return n;}
};
int main()
{// 1.基本方法Solution sl;sl.Sum_Solution(10);// 2.匿名对象Solution().Sum_Solution(10);return 0;
} 6. 拷贝对象时编译器做出的优化 在传参和传返回值的过程中一般编译器会做一些优化减少对象的拷贝这个在一些场景下还是非常有用的。 class A
{
public:A(int a 0):_a(a){cout A(int a) endl;}A(const A aa):_a(aa._a){cout A(const A aa) endl;}A operator(const A aa){cout A operator(const A aa) endl;if (this ! aa){_a aa._a;}return *this;}~A(){cout ~A() endl;}
private:int _a;
};
void f1(A aa)
{}
A f2()
{A aa;return aa;
}
int main()
{// 传值传参A aa1;f1(aa1);cout endl;// 传值返回f2();cout endl;// 隐式类型连续构造拷贝构造-优化为直接构造f1(1);// 一个表达式中连续构造拷贝构造-优化为一个构造f1(A(2));cout endl;// 一个表达式中连续拷贝构造拷贝构造-优化一个拷贝构造A aa2 f2();cout endl;// 一个表达式中连续拷贝构造赋值重载-无法优化aa1 f2();cout endl;return 0;
} 朋友们、伙计们美好的时光总是短暂的我们本期的的分享就到此结束欲知后事如何请听下回分解~最后看完别忘了留下你们弥足珍贵的三连喔感谢大家的支持