滴水三期:day44.1-private和class权限控制.

文章介绍了C++中将类的声明与实现分开的方法,强调了这样做对代码可读性的提升。同时,详细阐述了public和private权限的区别,public成员可以在任何地方使用,而private成员仅限类内部访问。文章还讨论了类的构造器默认为public以及如何通过指针访问private成员。此外,提到了class和struct在默认访问权限上的差异,并给出了相关示例。

一、方法定义和实现分开

  • 将声明与实现分离,代码会有更好的可读性,不是必须的

  • 选择项目Class View,右键新建Class;在xxx.h头文件中定义类,且只声明成员方法:

    struct Person{
    	int x;
    	void setx(int x);
    	int getx();
    };
    
  • ,在xxx.cpp中实现方法:(但是要告诉编译器,这不是一个普通的函数,而是Person类中的成员方法)

    void Person::setx(int x){
    	this->x = x;
    }
    int Person::getx(){
    	return this->x;
    }
    
  • 最后在要使用Person类中成员的cpp中include xxx.h引用头文件,就可以使用xxx.h中类创建对象,使用其属性和方法

    #include "stdafx.h"
    #include "MyClass.h"
    int main(int argc, char* argv[]){		
    	Person p;
    	p.setx(1);
    	printf("%d\n",p.getx());
    	return 0;	
    }
    
  • 特别说明:

    • xxx.h只是一个文件,头文件可以是任何的后缀名,不一定是.h,比如可以叫xxx.exe
    • #include 的作用只是把里面的内容复制过来,仅此而已
    • xxx.h 与 xxx.cpp并不要求一定同名

二、public和private

1.public权限说明

  • public权限:这个成员(属性、方法等)哪里都可以用,所以对外提供的函数或者变量,发布成public的
  • public/private可以修饰函数也可以修饰变量
  • 注意:目前阶段,类的构造器只能设置成public。后面学习设计模式时定义成private也有办法使用。

2.private权限说明

  • private权限:这个成员只用于类内部使用,即只有结构体内部的函数才可以访问private的成员,不能在其他的地方使用,所以不对外公布的,发布成private

  • 一般来说类的成员变量不能让别人轻易改动,如果要改动,也必须要对修改的值进行判断检验是否合法,所以一般都会对外发布可以修改或打印私有成员变量的方法,在方法中检验修改是否合法:

    #include "stdafx.h"	
    struct Person{
    private:   //私有成员变量
    	int age;
    public:  //共有成员方法
    	void SetAge(int age){
    		if(age > 0 && age <= 100){
    			this->age = age;  //private成员变量只有类中的其他成员可以访问
    		}
    	}
    	int GetAge(){
    		return age;
    	}
    };
    int main(int argc, char* argv[]){		
    	Person p;
        //不能p.age = 18;
    	p.SetAge(18);
    	printf("%d\n",p.GetAge());
    	return 0;	
    }
    
1)private成员分配空间
  • 当创建一个类的对象时,不管是公有变量还是私有变量,编译器分配空间时都一视同仁,还是会分配空间,只不过我们要使用私有变量时,编译器是不允许的

    #include "stdafx.h"	
    struct Person{
    private:
    	int x;
    	int y;
    public:
    	int z;
    	void Init(int x,int y,int z){
    		this->x = x;
    		this->y = y;
    		this->z = z;
    	}
    };
    int main(int argc, char* argv[]){		
    	Person p;
    	p.Init(1,2,3);
        printf("%d\n",sizeof(p));  //12,从这里也可以发现,不管私有还是公有成员变量,都会为其分配空间
    	return 0;	
    }
    

    查看反汇编发现:创建p对象后,最后一个参数就是对象的首地址,所以ebp-0xC也是成员x的地址,存到ecx寄存器中;接着进入到函数内部,ecx中就是x的地址(即对象首地址),然后把x的地址值存入到ebp-4,接着又把地址值存入到eax,所以mov dword ptr [eax],ecx就是在给成员x赋值;接着又把x的地址值存入到edx,所以[edx+4]中存的就是y;后面以此类推。还可以通过栈窗口发现,x,y,z成员就是挨着存的,看不出来哪一个是private哪一个是public

    image-20230424172836727 173205 image-20230424173648373
2)private成员变量其实可以访问
  • 前面讲过,不管是private成员变量还是public成员变量,在内存中都是一视同仁,就存储在对象的内存空间中,所以可以用指针访问即可

    #include "stdafx.h"	
    struct Person{
    private:
    	int x;
    	int y;
    public:
    	int z;
    	void Init(int x,int y,int z){
    		this->x = x;
    		this->y = y;
    		this->z = z;
    	}
    };
    int main(int argc, char* argv[]){		
    	Person p;
    	p.Init(1,2,3);
        
    	int* pp = (int*)&p;  //定义一个int*指针,访问x,y,z的值即可
    	printf("%d %d %d\n",*pp,*(pp + 1),*(pp + 2));  //1 2 3
    	return 0;	
    }
    
  • 所以再次印证了:private修饰的成员与普通的成员没有区别 只是编译器会检测

三、class和struct区别

  • 编译器默认class中的成员为private,而struct中的成员为public

  • 继承中的区别:

    • 如果一个子类继承一个父类时,没有声明以什么方式继承,默认以private的方式继承,即继承(复制)过来的成员都是私有的!

      #include "stdafx.h"	
      class Person{
      private:
      	int x;
      	int y;
      public:
      	int z;
      	void Init(int x,int y,int z){
      		this->x = x;
      		this->y = y;
      		this->z = z;
      	}
      };
      class Student:Person{  //由于这里没有声明以什么方式继承,默认以private方式继承
      private:
      	int m;
      public:
      	void changeZ(){
      		//z = 10;   //因为以private方式继承,即使父类中的z是public,但是继承来后就变成private
      		//x = 1;    //x本来就是私有的,当然使用不了
      	}
      };
      int main(int argc, char* argv[]){		
      	
      	return 0;	
      }
      
    • 如果子类中想使用父类中的public的变量或方法,就需要声明以public的方式继承

      class Student:public Person{  //以public方式继承
      private:
      	int m;
      public:
      	void changeZ(){
      		z = 10;   //因为以public方式继承,所以可以使用父类中public的成员
      		//x = 1;    //x本来就是私有的,当然使用不了
      	}
      };
      
    • 但是注意:父类中的私有成员是会被继承的,即还是会为私有成员变量分配空间,只是子类中无法使用父类的私有成员变量(所以说嘛,子类对象想访问父类中的私有成员变量,也是有办法的,和上面一样)

      #include "stdafx.h"	
      class Person{
      private:
      	int x;
      	int y;
      public:
      	int z;
      	Person(){
      		this->x = 1;
      		this->y = 2;
      		this->z = 3;
      	}
      };
      
      class Student:public Person{
      private:
      	int m;
      public:
      	void changeZ(){
      		m = 4;
      	}
      };
      int main(int argc, char* argv[]){		
      	Student stu;  //创建子类对象时,是会先调用父类的构造器的!所以x,y,z才会被赋值1,2,3
      	stu.changeZ();
      
      	int* stup = (int*)&stu;
          printf("%d\n",sizeof(stu)); //16,说明父类中无论私有公有的成员变量都被继承过来了
      	printf("%d %d %d %d\n",*(stup),*(stup + 1),*(stup + 2),*(stup + 3)); //1 2 3 4
      	return 0;	
      }
      

四、作业

1.class和private练习

  • 将上一节课的所有练习改为class实现,并添加private/public进行权限控制,而且将类的定义与实现分开来写:定义写到xxx.h中,函数实现写在xxx.cpp中

  • 在MyClass.h中声明DataInfo类,TimeInfo类:

    #if !defined(AFX_MYCLASS_H__44CA5D47_B224_42F2_A26E_CAD8CD157CD1__INCLUDED_)
    #define AFX_MYCLASS_H__44CA5D47_B224_42F2_A26E_CAD8CD157CD1__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    class DataInfo{
    private:
        int year;
    	int month;
    	int day;
    public:
    	DataInfo(int year,int month,int day){
    		this->year = year;
    		this->month = month;
    		this->day = day;
    	}
    	DataInfo(){
    		year = 2015;
    		month = 4;
    		day = 2;
    	}
                                      
    	void SetDay(int day);
    	int GetDay();
    	void SetYear(int year);
    	int GetYear();
    	void SetMonth(int month);
    	int GetMonth();
    };
    class TimeInfo:public DataInfo{
    private:
    	int hour;
    	int minute;
    	int second;
    public:
    	void SetHour(int hour);
    	void SetMinute(int minute);
    	void SetSecond(int second);
    	int GetHour();
    	int GetMinute();
    	int GetSecond();
    };
    #endif // !defined(AFX_MYCLASS_H__44CA5D47_B224_42F2_A26E_CAD8CD157CD1__INCLUDED_)
    
    184641
  • 在MyClass.cpp中实现方法:

    #include "stdafx.h"
    #include "MyClass.h"
    void DataInfo::SetDay(int day){
    	this->day = day;
    }
    int DataInfo::GetDay(){
    	return day;
    }
    void DataInfo::SetYear(int year){
    	this->year = year;
    }
    int DataInfo::GetYear(){
    	return year;
    }
    void DataInfo::SetMonth(int month){
    	this->month = month;
    }
    int DataInfo::GetMonth(){
    	return month;
    }
    
    void TimeInfo::SetHour(int hour){
    	this->hour = hour;
    }
    void TimeInfo::SetMinute(int minute){
    	this->minute = minute;
    }
    void TimeInfo::SetSecond(int second){
    	this->second = second;
    }
    int TimeInfo::GetHour(){
    	return hour;
    }
    int TimeInfo::GetMinute(){
    	return minute;
    }
    int TimeInfo::GetSecond(){
    	return second;
    }
    
    184831
  • 最后在要使用的cpp中包含MyClass头文件,创建对象并使用成员方法打印日期:

    #include "stdafx.h"
    #include "MyClass.h"
    void Test(){
    	//访问TimeInfo对象的成员
    	TimeInfo t;
    	t.SetHour(21);
    	t.SetMinute(8);
    	t.SetSecond(52);	
    	printf("%04d.%02d.%02d - %02d:%02d:%02d\n",t.GetYear(),t.GetMonth(),t.GetDay(),t.GetHour(),t.GetMinute(),t.GetSecond());
    }
    int main(int argc, char* argv[]){		
    	Test();
    	return 0;	
    }
    
    185024
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值