类和对象补充

const 成员函数

const修饰的成员函数称之为const成员函数,const修饰成员函数放到成员函数参数列表的后面。

void Print() const
 {
 cout << _year << "-" << _month << "-" << _day << endl;
 }

为什么要用const进行修饰

使用const修饰主要就是权限放大缩小的问题,这里我们能看见这里显示报错,那么报错的报错的原因就是权限的放大,这里传入的时候限制是不能改变指向的内容,而接收的权限是可以改变指向的内容,因此涉及权限放大,为了解决这一问题只需要在函数的后面加上const即可把Data *const this ——>const Data *const this。

 const修饰的函数优缺点

通过const进行修改后,普通类型的也可以进行访问被const修饰的函数。这并不意味着所有的都可以这样设置,因为经过修饰后权限被缩小,只能读所指向的内容并不能所指向的内容进行修改。

案例如下:

取地址运算符重载

取地址运算符重载分为普通取地址运算符重载和const取地址运算符重载,⼀般这两个函数编译器自动生成的就可以够我们用了,不需要去显示实现。

Date* operator&()

{

        return this; 

}

const Date* operator&()const

{

        return this; 

}

再探构造函数

初始化列表

初始化列表的使用方式式是以⼀个冒号开始,接着是⼀个以逗号分隔的数据成员列表,每个"成员变量"后面跟⼀个放在括号中的初始值或表达式。注意:每个成员变量在初始化列表中只能出现⼀次

Date(int year = 1, int month = 1, int day = 1)

         :_year(year)

        ,_month(month)

        ,_day(day)

必须使用初始化列表的三种情况

引用成员变量,const成员变量,没有默认构造的类类型成员变量。为什么以上三种要用初始化列表,因为引用必须在定义的时候进行初始化,const也是在初始化的那一刻才能进行初值的改变,没有默认构造,调用的时候需要传参,传参就要初始化,初始化只能在初始化列表中,因为在函数体成员可以出现多次那么到底那个是初始化,这就产出了问题,所以通俗说初始化列表可以认为是每个成员变量定义初始化的地方

面试题分析

初始化列表中按照成员变量在类中声明顺序进行初始化,跟成员在初始化列表出现的的先后顺序无关。建议声明顺序和初始化列表顺序保持⼀致。此题先按照声明的顺序,先执行_a2(),此时a1还未进行传入,这时_a2就会显示随机值,_a1为1。

初始化列表总结

类型转换   

C++⽀持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数。如我们学过的指针(虽然存放的是地址,也是有编号)可以和数据类型进行相互转换。

什么是隐式类型转换

A类只有一个单参数的构造函数,因此该构造函数是支持隐式类型转换的,A aa1 = 1;本质上就是隐式类型转换,首先在隐式转换过程中会产生一个临时的中间变量,用1去调用构造函数,得到一个A类型的临时中间变量,然后再用这个A类型的中间变量去调用拷贝构造,最终完成aa1的创建。

#include<iostream>
using namespace std;
class A
{
public:
	// 构造函数explicit就不再⽀持隐式类型转换 
	// explicit A(int a1)
	A(int a1)
		:_a1(a1)
	{}
	
	A(int a1, int a2)
		:_a1(a1)
		, _a2(a2)
	{}
	void Print()
	{
		cout << _a1 << " " << _a2 << endl;
	}
private:
	int _a1 = 1;
	int _a2 = 2;
};

int main()
{
	
	A aa1 = 1;
	aa1.Print();
    //用于检测是否创建了中间变量
    //临时对象具有常性,不能放大权限,如果创建了不加const限定就会报错
    
	//const A& aa2 = 1;
	
	return 0;
}

explicit的用法

构造函数前加explicit就不再支持隐式类型转换

用法如下:explicit A(int a1)

static关键字

static成员变量的用法

  1. 用static修饰的成员变量,称之为静态成员变量,静态成员变量⼀定要在类外进行初始化。在类外初始化要记得加上类域这要就知道是静态成员变量。
  2. 静态成员变量为所有类对象所共享,不属于某个具体的对象,不存在对象中,存放在静态区。
  3.  静态成员也是类的成员,受public、protected、private访问限定符的限制。
  4.  静态成员变量不能在声明位置给缺省值初始化,因为缺省值是构造函数初始化列表的,静态成员 变量不属于某个对象,不⾛构造函数初始化列表。

static成员函数的特点

  1. 用static修饰的成员函数,称之为静态成员函数,静态成员函数没有this指针。
  2. 静态成员函数中可以访问其他的静态成员,但是不能访问⾮静态的,因为没有this指针。
  3. 非静态的成员函数,可以访问任意的静态成员变量和静态成员函数。
  4. 突破类域就可以访问静态成员,可以通过类名::静态成员或者对象.静态成员来访问静态成员变量 和静态成员函数。

面试小案列

 构造函数的调用顺序是 :先全局然后按照声明的顺序进行构造函数的调用,因此构造函数的调用   顺序为:   C A B D。

析构函数调用的顺序:按照后构造的先析构,最后析构全局的构造函数。所以顺序为:B A D C。

友员补充

友元函数

  1. 在函数声明或者类 声明的前面加friend,并且把友元声明放到⼀个类的里面。
  2.  外部友元函数可访问类的私有和保护成员,友元函数仅仅是⼀种声明,他不是类的成员函数。
  3. 友元函数可以在类定义的任何地方声明,不受类访问限定符限制。
  4. ⼀个函数可以是多个类的友元函数。

友元类

  1. 友元类中的成员函数都可以是另⼀个类的友元函数,都可以访问另⼀个类中的私有和保护成员。
  2. 友元类的关系是单向的,不具有交换性,如A类是B类的友元,但是B类不是A类的友元。
  3. 友元类关系不能传递,如果A是B的友元,B是C的友元,但是A不是C的友元。
  4. 有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

 内部类

内部类就是把一个类写在另一个类的里面,这种就叫做内部类。他只是受外部类类域限制和访问限定符限制。内部类并不占用所写入类的字节大小。

注意:内部类默认是外部类的友元类。因此在访问静态成员变量的时候可以直接使用,普通的成员需要引用外部类名。内部类本质也是⼀种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使用。在内部类上加上private/protected专属内部类,其他地方就无法使用了。

#include<iostream>
using namespace std;
class A
{
   private:
     static int _k;
     int _h = 1;
   public:
     class B // B默认就是A的友元 
     {
         public:
            void foo(const A& a)
            {
             cout << _k << endl; 
             cout << a._h << endl; 
            }
        private:
            int b=1;
     };
};

int A::_k = 1;
int main()
{
 cout << sizeof(A) << endl;
 A::B b;
 A aa;
 b.foo(aa);
 return 0;
}

 匿名对象

没有名字的对象通常写成类型(实参)。匿名对象生命周期只在当前一行,而有名对象的生命周期是这个main()函数调用结束。匿名对象可以引用,引用后就具有了常性,需要加const加完const之后生命周期变长。

class A

{

        public:

                A(int a = 0)

                        :_a(a)

                {

                        cout <<"A(int a)"<<endl;

                }

                ~A()

                {

                        cout <<"~A()"<<endl;

        private:

                int _a;

};

int main()

{

        //匿名对象的使用方式

        A();

        A(1);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值