C++(2023.5.8)

目录

在声明的时候,给成员变量缺省值比较方便

指针和引用都涉及到权限

取地址运算符重载

只有一种场景下需要我们自己写

类和对象(下)

构造函数初始化两种方式

构造函数体赋值

初始化列表(对象的成员定义的位置,声明的顺序一定要跟定义的顺序保持一致)

为什么有初始化列表,还要有函数体内赋值?

初始化列表是有顺序的

程序崩溃

隐式类型转换

explicit(拒绝发生隐式转换)

Static

静态成员变量(在类外面定义)

静态成员函数

(非静态成员函数和非静态成员变量)与静态成员函数的关系

设计一个类只能在栈或堆上创建对象


在声明的时候,给成员变量缺省值比较方便

指针和引用都涉及到权限

权限可以缩小,可以平移,但是不能放大

取地址运算符重载

不写编译器也会自动生成

只有一种场景下需要我们自己写

不希望别人取到地址

默认成员函数都不能重载成全局,编译器会默认生成一个,导致歧义

类和对象(下)

构造函数初始化两种方式

构造函数体赋值

初始化列表(对象的成员定义的位置,声明的顺序一定要跟定义的顺序保持一致

初始化列表是构造函数的一部分

它替代的是函数体内赋值

我们不写每一个成员变量也会走初始化列表、

声明的顺序一定要跟定义的顺序保持一致

成员变量最多会走一次初始化列表,也最少会走一次初始化列表,有且只能出现一次

三种必须在初始化列表

引用,const,没有默认构造函数
        引用与const的特征:必须在定义的时候初始化

#include<iostream>

using namespace std;

class A
{
public:
	//默认生成构造函数,内置类型不做处理,自定义类型调用它的默认构造函数
	A(int a,double b)
		:_a(a)
		,_b(b)
	{
		cout <<"A(int a = 0)"<< endl;
	}
private:
	int _a;
	double _b;
};

class B
{
public:
	//初始化列表:对象的成员定义的位置
	
	//1.B(int a=1,int ref=1)
    //2.
    B(int a=1,int ref&=1)
		:_n(a)
		,_ref(ref)//按1走,ref是局部变量,这里会有野引用问题发生
                 //所以这里需要像2传引用
		,aobj(3,3.14)//没有默认构造时
	{
		/*_n = 0;
		_ref = ref;*/
	}

	private:
		//声明
		
		A aobj;//没有默认构造函数:A(int a ,double b)
		//默认构造:编译器默认生成,全缺省,无参

        //引用与const的特征:必须在定义的时候初始化
		int& _ref;//引用
		const int _n;//const
		int _x=1;//这里1是缺省值,缺省值是给初始化列表的

};

int main()
{
    int n=1;
    int m=2;
	//对象整体定义
	//B bb1(10, 1);
    B bb1(10, n);
	//B bb2(11, 2);
    B bb2(11, m);

	return 0;
}

在初始化列表时,内置类型会走初始化列表,但如果没传值,就不做处理,自定义类型会去调用它的默认构造函数

为什么有初始化列表,还要有函数体内赋值?

因为有一些工作是初始化列表做不了的

例如:在初始化列表就无法检查开辟空间

动态开辟二维数组

初始化列表是有顺序的

初始化列表有顺序,按照声明顺序进行初始化,声明顺序跟定义顺序保持一致

容易写成这种问题

 

程序崩溃

野指针,内存越界

先走初始化列表,在走赋值

隐式类型转换

//隐式类型转换
class A
{
public:
	//构造函数
	A(int a=1)
		: _a(a)
	{
		cout << "A(int a)" << endl;
	}

	//拷贝构造
	A( const A& aa)
		:_a(aa._a)
	{
		cout << "A(const A& aa))" << endl;
	}

private:
	int _a=1;
};

int main()
{
	A a(2);
	A b = 2;
	const A & c = 2;
	return 0;
}

class string
{
public:
	string(const char* str)
	{}
};

class list
{
public:
	void push_back(const string& str)
	{}
};

int main()
{
	string name1("张三");
	string name2 = "张三";

	list lt1;

//两种方法,意义一样,下面的是因为隐式类型转换
	string name3("李四");
	lt1.push_back(name3);

	lt1.push_back("李四");

	return 0;
}

explicit(拒绝发生隐式转换)

如果不想要转换发生可以在构造函数前加一个explicit

Static

全局变量的劣势:任何地方都可以随意改变。

在类里面写静态变量,相当于用类去封装全局变量

并且不能给缺省值,因为静态变量没有初始化列表,缺省值是给初始化列表的

静态成员变量(在类外面定义)

成员变量—— 每一个对象都自己的成员变量,存储在对象里面

 静态成员变量——属于类,属于类的每个对象共享,存储在静态区(它的生命周期是全局的)

不能在初始化列表中初始化,因为它不属于某个对象

可以通过公有的成员函数,访问私有变量

void Getdataname()

cout<<dataname<<endl;

静态成员函数

没有this指针,指定类域(类的名字)和访问限定符(::)就可以访问

#include<iostream>

using namespace std;

//计算还有多少个对象存在
class A
{
public:
	A()
	{
		_count++;
	}

	~A()
	{
	_count--;
	}

	//静态成员函数没有this指针
	//两种不同书写方式,打印方法也不同
	/*static void Get_count()
	{
		cout << A::_count << endl;

	}*/
	//A::Get_count();

	static int Get_count()
	{

			return _count;
	}
	//cout << __LINE__<<":" << A::Get_count () << endl;

private:
	static int _count;
};

//全局位置,类外面定义
int A::_count = 0;

A aa;

void func()
{
	//静态变量只能定义一次
	static A aa1;
	/*cout << __LINE__ <<":"<<aa1.Get_count() << endl;*/
	A::Get_count();

}

int main()
{

	/*A::Get_count();*/

	cout << __LINE__<<":" << A::Get_count () << endl;

	A aa1;
	func();
	func();
}

(非静态成员函数和非静态成员变量)与静态成员函数的关系

非静态能否调用静态:可以

  静态能否调用非静态:不可以。非静态的成员函数调用需要this指针,没有this指针

//class A
//{
//public:
//	A() 
//	{
//		++_scount;
//	}
//
//	A(const A& t) 
//	{
//		++_scount;
//	}
//
//	~A() 
//	{ 
//		--_scount;
//	}
//
//
//	void Func1()
//	{
//		// 非静态能否调用静态:可以
//		GetACount();
//	}
//
//	void Func2()
//	{
//		++_a1;
//	}
//
//	// 没有this指针,指定类域和访问限定符就可以访问
//	static int GetACount() 
//	{ 
//		// 静态能否调用非静态:不可以。非静态的成员函数调用需要this指针,我没有this
//		// Func2();
//
//		//_a1++;
//		return _scount;
//	}
//private:
//	// 成员变量 -- 属于每个一个类对象,存储对象里面
//	int _a1 = 1;
//	int _a2 = 2;
public:
//	// 静态成员变量 -- 属于类,属于类的每个对象共享,存储在静态区
//	static int _scount;
//};

设计一个类只能在栈或堆上创建对象

class A
{
public:
	static A GetStackObj()
	{
		A aa;
		return aa;
	}

	static A* GetHeapObj()
	{
		return new A;
	}
private:
	A()
	{}

private:
	int _a1 = 1;
	int _a2 = 2;
};

int main()
{
	//static A aa1;   //  静态区
	//A aa2;          //  栈 
	//A* ptr = new A; //  堆
	A::GetStackObj();
	A::GetHeapObj();

	return 0;
}

访问限度符限度的是成员访问方式:成员变量,成员函数

友元

友元是一个声明,可以在类中任意位置

友元函数

耦合度太高,牵一发而动全身

可以声明在任意位置

友元类

#include<iostream>
#include<string>
using namespace std;

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

2023.5.10

内部类

内部类分为两种:公有的内部类与私有的内部类

但是它受访问限度符限制

内部类在类里面声明不占空间,定义才占空间

定位了一个B类就变成了12;

内部类是外部类的天生友元;、

内部类能够访问外部类的数据,但外部类不能访问内部类的信息

 

匿名对象(即用即销毁)

类名+(参数)

匿名对象具有常性

const A& ra = A(2);//const引用延长匿名对象的生命周期,生命周期在当前函数局部域,

 

//匿名对象
class A
{
public:
	//构造函数
	A(int a=1)
		:_a(a)
	{
		cout << "A(int a)" << endl;
	}

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

private:
	int _a=1;
};

class Solution
{
public:
	Solution()
	{
		
	}

	~Solution()
	{
		cout << "~Solution()" << endl;
	}

	int Sum_Solution(int n)
	{
		cout << "Sum_Solution" << endl;

		return n;
	}
};

	int main()
	{
		A a(2);//有名对象--生命周期在当前函数局部域

		//匿名对象即用即销毁
		A(2);//匿名对象--生命周期在当前行
		A();//可以理解成后面就没人用了,就直接销毁了


		// A& ra = A(1);//匿名对象具有常性
		const A& ra = A(2);//const引用延长匿名对象的生命周期,生命周期在当前函数局部域,
		//可以理解为因为后面ra还会用这个匿名对象,所以没有销毁



		//创建对象,调用函数
		 Solution b;
	
		//有名对象不能这样写  Solution A();  因为编译器不知道这是对象,还是函数声明
		 b.Sum_Solution(10);
		

		//匿名对象调用函数,还是会先走构造函数,再进入调用的函数,必须加一个括号,
		//有默认构造函数不要传参,没有的话正常传参
		Solution().Sum_Solution(10);
		//Solution::Sum_Solution(10);错误调用,没有this指针可以传递


		return 0;
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值