【c++类和对象语法补充】const成员,构造函数的补充,声明缺省值,友元

目录

1.const成员

2.构造函数的补充

                1.构造函数体赋值

                2.初始化列表

                3.explicit关键字

3.C++11 的成员初始化新玩法(声明缺省值)

4.友元(友元函数,友元类(内部类))

                1.友元函数

                2. 友元类

                3.内部类(了解,不怎么用)


1.const成员

将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this 指针,表明在该成员函数中不能对类的任何成员进行修改

如果你的this指针不会被修改,都推荐加一个const

	
//有2个参数一个是隐含的this指针,const修饰的是this,另一个是cmp
//即bool operator==(Date& this(隐含),Date& cmp)const
bool operator==(Date& cmp)const//const修饰成员函数
	{
		return _year == cmp._year &&
			_month == cmp._month &&
			_day == cmp._day;
	}

2.构造函数的补充

                1.构造函数体赋值

构造函数体中的语句只能将其称作为赋初值,不能称作初始化,初始化定义应该是只能初始化一次,而构造函数体内可以多次赋值(就像下面代码_day先赋值5再赋值我们给的参数)

class Date
{
public:
	Date(int year=2022, int month=2, int day=2)
	{
		_year = year;
		_month = month;
        _day=5;
		_day = day;
	}
	
private:
	int _year;
	int _month;
	int _day;
};

                2.初始化列表

  1. 格式: 以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式
  2. 说明:每个成员变量只能初始化一次{}即是构造函数体赋值所有可以多次赋值。(初始化列表是成员变量的定义
class Date
{
public:
	Date(int year = 2022, int month = 2, int day = 2)
		//有三种必须在初始化列表初始化
	:_year(1)
    ,_month(month)
    ,_day(day)
    {}//构造函数体赋值
	
private:
	int _year;
	int _month;
	int _day;
};
  1.  必须放在初始化列表位置进行初始化有3个:引用成员变量,const成员变量,自定义类型成员(该类没有默认构造函数)因为它们都是需要定义;初始化列表是成员变量的定义;
  2. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使 用初始化列表初始化;(因为初始化列表是定义)
  3. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关(调试如下)

class A
{
public:
	A(int a=10)
	{
		cout << "A" << endl;
		_a = a;
	}
private:
	int _a;

};

class Date
{
public:
	//可以理解成,一个对象的成员变量在初始化列表是成员变量的定义
	//这个可以算是初始化列表和函数体内初始化不同的地方,也是它价值的体现(有三种必须在初始化列表初始化)
	Date(int year = 2022, int month = 2, int day = 2)
		//有三种必须在初始化列表初始化
		:_year(year)
        , _day(day)
		, _month(month)
		, _c(year)//引用成员变量
		, _n(10)//const成员变量
		, _a(20)//自定义类型成员(类没有默认构造函数)
	{
		_year = year;//函数结构体内初始化
		//不能在函数体内初始化,必须使用初始化列表初始化
		//函数体内初始化并不是初始化,而是对成员变量的再处理
		//_c = year;
		//_n = 10;
		//_a = 20;
	}
private:
	//成员变量声明的次序就是初始化列表中的初始化顺序,与其它在初始化列表的先后顺序无关
	//成员变量声明
	int _year;
	int _month;
    int _day;

	//必须在定义时候初始化
	const int _n;
	int& _c;
	A _a;
};

                3.explicit关键字

对于单个参数的构造函数,还具有类型转换的作用

  1. 单个参数的构造函数,支持隐式类型转换
  2. 早时期:先创造一个临时变量A tmp(2),再拷贝构造A a2(tmp);现在编译器做了优化:A a2(2);
  3. explicit,不想发生隐式类型转换加一个explicit,即不能使用A a2=2这样的形式;

class A
{
public:
	//explicit不想发生隐式类型转换加一个explicit
	A(int a=100)
	{
		_a = a;
	}
	explicit A(int a=100)
	{
		_a = a;
	}
	
private:
	int _a;
};
int main()
{
	A a1(1);
	//单个参数的构造函数,支持隐式类型转换
	A a2 = 2;//早时期:先创造一个临时变量A tmp(2),再拷贝构造A a2(tmp);现在编译器做了优化:A a2(2);
	A(3);//构造匿名对象,生命周期就在这一行,生命周期结束调析构;
	A();
	return 0;
}

3.C++11 的成员初始化新玩法(声明缺省值)

说明:如果没有初始化列表初始化,那么就会使用声明缺省值来初始值;即看代码中:_a(a)     ,_p(p)使用了列表初始化,那么不使用声明缺省值,但是arr和_b没有初始化那么使用声明缺省值;

#include <iostream>
using namespace std;
class B
{
public:
	B(int x = 0)
	{
		_x = x;
	}
private:
	int _x;
};
class A
{
public:
	A(int a=1,int* p=nullptr)
		:_a(a)
		,_p(p)
		{
		}
private:
	//声明缺省值
	int _a=0;
	int* _p=nullptr;
	int* arr = (int*)malloc(sizeof(int));
	B _b=6;
};
int main()
{
	A a;
	return 0;
}

4.友元(友元函数,友元类(内部类))

                1.友元函数

友元函数可访问类的私有和保护成员但不是类的成员函数

  • 友元函数不能用const修饰
  • 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
  • 一个函数可以是多个类的友元函数
    • 友元函数的调用与普通函数的调用和原理相同
      #include <iostream>
      using namespace std;
      
      class Date
      {
      	friend ostream& operator<<(ostream& out, const Date& d);
      	friend istream& operator>>(istream& in, Date& d);
      
      public:
      
      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()
      {
      	return 0;
      }

                      2. 友元类

友元函数可访问类的私有和保护成员,但不是类的成员函数

  • 友元关系是单向的,不具有交换性;Dates是Time的友元,Time不是Date的友元

  • 友元关系不能传递,如果B是A的友元,C是B的友元,则不能说明C时A的友元

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;
};

                3.内部类(了解,不怎么用)

  • 内部类可以定义在外部类的public、protected、private都是可以的。
  • 注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名
  • sizeof(外部类)=外部类,和内部类没有任何关系。
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::B b;
 b.foo(A());
 
 return 0;
}

如果有没有理解的,评论区我会回复 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值