c++基础知识(3)析构函数.static.const.友元函数

本文详细介绍了C++中的析构函数,包括何时自动调用、如何处理资源释放以及注意事项。同时,探讨了静态成员的用法,包括全局静态变量、局部静态变量以及静态成员函数的特性。此外,还阐述了const在类成员变量和成员函数中的应用,强调其在保护数据不变性方面的重要性。最后,提到了友元函数的概念及其在访问类私有成员时的角色。
摘要由CSDN通过智能技术生成

一.析构函数:对象销毁自动调用的函数,它可以显示使用

~类名(void)

注意:

1.当存在移动构造时,需要在释放空间之前判断是否是临时变量,如果是临时变量则不需要释放

2.使用析构显示调用时需要注意重复释放的问题

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

class String{
	
	public:
		//普通构造
		String(const char*p)
		{
			/*
			if(nullptr == p)
				异常处理
			*/
			cout<<"normal"<<endl;
			addr = new char[strlen(p)+1];  //开辟空间
			strcpy(addr, p);
			len = strlen(p);
		}
		//深拷贝
		String(const String & obj)
		{
			cout<<"cpy"<<endl;
			addr = new char[strlen(obj.addr)+1];
			strcpy(addr,obj.addr);
			len = obj.len;
		}
		//移动构造
		String(String && obj)
		{
			cout<<"move"<<endl;
			addr = obj.addr;
			obj.addr = nullptr;
			len = obj.len;
		}

        ~String()
        {
            cout<<"delte"<<endl;
            if(addr != nullptr)
            {
                delete []addr;
                addr = nullptr;
            }
        }
		char &at(const int id)   //因为需要通过返回值修改成员变量所以使用引用
		{
			return addr[id];			
		}
		
		char* get_addr()
		{
			return addr;
		}
		
		void setval(const char* p)
		{
			
			if(strlen(p) > len)
			{
				//p大于原来的空间,应该重新开辟一个空间
				delete []addr;
				addr = new char[strlen(p)+1];
				
				strcpy(addr, p);
				len =  strlen(p);
			}
			else
			{
				strcpy(addr, p);
				len =  strlen(p);
			}
		}
		
		void append(const char* p)
		{
			char buf[len+1];    //存储原始数据
			strcpy(buf, addr);
			delete []addr;
			addr = new char[len+strlen(p)+1];
			
			strcpy(addr, buf);
			strcat(addr, p);
			len += strlen(p); 
		}
	private:
		char *addr;
		int len;
};

void test()
{
    char buf[100] = "hello";
    String A = buf;

}

int main()
{
    test();
    while(1);
}

二.static

1.修饰变量

{

        1.修饰全局变量,生命周期不变,作用域被限制在本文件

        2.修饰局部变量,延长生命周期到程序结束,作用域不变

}

2.修饰函数

{

        1.修饰函数,生命周期不变,作用域限制在本文件

}

3.修饰类相关

[

        特点:静态成员,不和具体对象关联,没有对象生成静态成员也存在                        

                   静态成员不属于类,多个对象公用一个静态成员

                   静态成员使用之前必须初始化,类型+类名::变量名=n;

                   联系:利用static变量,计算某个类对象个数

修饰共有成员

#include <iostream>

using namespace std;

class demo{

    public:
        void setval(int n)
        {
            demo::a = n;
        }
        
        int getval()
        {
            return demo::a;
        }
		
        static int a;
        //int b;
};

int demo::a = 1; //static init

int main()
{
   // demo  b;

    demo::a=100;

    cout<<demo::a<<endl;

}

修饰私有成员

#include <iostream>

using namespace std;

class demo{

    public:
        void setval(int n)
        {
            demo::a = n;
        }
        
        int getval()
        {
            return demo::a;
        }
	private:
		static int a;
        //int b;
};

int demo::a = 1; //static init

int main()
{
    demo  b, c;

   //因为静态变量只有一份,所以b改成10, c打印依然是10 
    cout<<b.getval()<<endl;
    cout<<c.getval()<<endl;
    b.setval(10); 
    cout<<b.getval()<<endl;
    cout<<c.getval()<<endl;

	cout<<sizeof(demo)<<endl;//打印出来是1,说明静态成员不属于类
}

1.修饰成员变量的情况

2.修饰成员函数

{

        (1).不能访问非静态的类成员

        (2).非静态的类成员可以访问静态成员

        (3).静态成员没有this指针

#include <iostream>

using namespace std;

class demo{
    public:
        demo()
        {
            a++;
        }
        demo(demo&obj)
        {
            a++;
        }
        demo(demo &&obj)
        {
            a++;
        }

        static int getval()
        {
            return a;
        }
        
        void func()
        {
            getval();
        }

        ~demo()
        {
            a--;
        }
    private:
        static int a;
        int b;
};

int demo::a = 0;

void func()
{
    //demo A,B,C;
    cout<<demo::getval()<<endl;
}

int main(int argc, char *argv[])
{ 

    //demo A, B, C;

    func();
    cout<<demo::getval()<<endl;

    return 0;
} 

              关于this指针

                {

                        thie指针       

#include <iostream>

class demo{
    
    public:
        //形参和成员变量同名
        void setval(int a)
        {
            this->a=a;
        }
        
        //返回对象指针
        demo *func()
        {
            return this;
        }
        //返回对象
        demo &func()
        {
            return *this;
        }

    private:
        int a;

}

int main()
{
    demo A;
}

               

                }

}

]

三.const

1.const修饰类的成员变量:

(1).修饰的变量不能被更改,const修饰的变量需要初始化

(2).const修饰的成员变量,必须使用初始化列表进行初始化

(3).非const成员函数可以访问const修饰的变量

初始化列表

{

        1.可以初始化const修饰的变量,也可以初始化非const修饰的变量

}

#include <iostream>
using namespace std;
class demo{
   // 非const成员函数可以访问,const成员变量
    public:
        demo(int n, char c , int *p):
            a(n),ch(c),b{p[0], p[1], p[2]} //初始化列表格式,分别对int,char,数组,进行的初始化
        {
        
        }
        
        void printf_demo()
        {
            cout<<a<<ch<<endl;
            cout<<b[0]<<b[1]<<b[2]<<endl;
        }
    private:
        const int a;
        const char ch;
        int b[3];
};


int main()
{
    int buf[3] = {1,2,3};
    demo A(10, 'A',buf);

    A.printf_demo();


}

2.const修饰函数

格式:  返回值 函数名()const

    1.const修饰的函数可以访问const成员

    2.const修饰的函数可以访问非const成员

重点3.函数内部不能出现修改变成员量值的逻辑出现!

可以看出其实const的作用并不在于访问,而是在与改不改变

#include <iostream>
using namespace std;
class demo{
   // 非const成员函数可以访问,const成员变量
    public:
        demo(int n, char c , int *p):
            a(n),ch(c),b{p[0], p[1], p[2]} //初始化列表格式,分别对int,char,数组,进行的初始化
        {
        
        }
        
        void printf_demo()
        {
            cout<<a<<ch<<endl;
            cout<<b[0]<<b[1]<<b[2]<<endl;
        }

        int &func()const{
            cout<<b[0]<<endl;  //1.const修饰的函数可以访问非const成员
            cout<<a<<endl;    //2.const修饰的函数可以访问const成员
            
            //return b[0];      // err,因为引用有可能改变数据,所以就是没改也过不了
        }
    private:
        const int a;
        const char ch;
        int b[3];
};


int main()
{
    int buf[3] = {1,2,3};
    demo A(10, 'A',buf);

    A.func();

}

3.const修饰类

   1.const修饰的对象,只能访问有const修饰的函数

四.友元函数

面向对象的特点

1.封装:安全

2.继承

3.多态

友元函数

#include <iostream>

using namespace std;

class demo{


    private:
        friend void func(demo A);  //友元函数声明
        int a;
};

void func(demo A)
{
    cout<<A.a<<endl;
}

int main()
{
    demo A;
    func(A);   
}

作用:友元函数可以访问类的私有空间

一.全局函数作为友元函数

二.友元类  向前声明、

#include <iostream>

using namespace std;

class B; //向前声明

class A{
    
    private:
        friend class B;
        int i;
};

class B{

    public:
        void func(A obj)
        {
            cout<<obj.i<<endl;
        }


    private:
        int j;
};

int main()
{
    B i;
    A j;

    i.func(j);
}

三.类的成员函数是另一个类的友元函数

#include <iostream>

using namespace std;

class A;

class B{
    
    public:
        void func(A obj);

    private:

};

class A{

    public:
        friend void B::func(A obj);

    private:
        int i;
};

void B::func(A obj)
{
    cout<<obj.i<<endl;
}
int main()
{
    A i;
    B j;

    j.func(i);
}

1.友元函数内部没有this指针

2.打破了封装,不安全(避免使用)

3.需要频繁访问数据,使用友元会更快捷

关键字 friend

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞赴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值