C++的公有与私有

本文探讨了C++中class的默认访问权限为私有,强调了public和private的区别。初始化与赋值之间的差异被阐述,初始化在内存分配时进行,而赋值则在其后。初始化列表仅存在于构造函数中,对于const成员和引用成员至关重要。常对象只能调用常方法,而常方法不能修改成员,除非它们是静态的或不会暴露成员的引用或指针。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • C语言中struct 默认是公有成员,C++中class 默认是私有成员
  • private:除了类内部之外都不可以使用 
  • public:对外暴露的,外界会具有读写操作权限

权限选择:必须要对外界提供的,放在public,其余的都放在private

class Person
{
private:
	int _age;
	int _sex;
	char* _name; //这三个成员属性默认为私有,但可以通过函数接口去使用它们
public:
	
	Person()
	{
		cout << "Person()" << endl;
	}
	Person(int age)
	{
		cout << "Person(int age)" << endl;
		_age = age;
		_name = NULL;
	}
	int Get_age()  //通过函数接口可以读取年龄值
	{
		return _age;
	}
	void Set_age(int age) //通过函数接口可以改变年龄值
	{
		_age = age;
	}
	//但是这样的化_age属性与共有存在没有区别,都可以读或者改变_age的值
	//所以一般在使用时,我们都会设置访问这些属性的身份,如下:
	void Set_age(int age, int who)
	{
		if (who == 1)
		{
			_age = age;
		}
	}
	
	~Person()
	{
		cout << "~Person" << endl;
		delete[]_name;
	}
};

初始化与赋值的区别

  • 初始化:在定义的时候给值,内存划分时候给值
  • 赋值:定义之后给值,内存划分完后之后给值

初始化列表

  • 只有构造函数有初始化列表
  • 必须初始化的成员需要放在初始化列表,eg:const成员和引用成员必须初始化,所以必须放在初始化列表,因为在编译时期将有引用的的地方都换成了引用底层的解引用
  • 在本对象构造之前需要完成的动作,必须放在初始化列表
  • 拷贝函数依然是构造函数,所以它也应该有初始化列表
int id;
class Person
{
private:
	int _age;
	const int _sex;
	char* _name; 
	int& ID;
public:
	
	Person():_sex(1), ID(id) //const与引用都必须在初始化列表
	{
		cout << "Person()" << endl;
	}
	Person(int age) :_sex(1), ID(id)
	{
		cout << "Person(int age)" << endl;
		_name = NULL;
	}
	
	~Person()
	{
		cout << "~Person" << endl;
		delete[]_name;
	}
};

const常对象

  • 常对象只能调用常方法,构造函数,析构函数,静态函数不影响
  • 常方法中只能调用常方法,静态函数不影响
  • 普通对象调用常方法是可以的,常对象不能调用普通方法
  • 哪些成员方法需要写成常方法:1.如果成员方法内不需要改动成员,并且没有对外暴露成员引用或者指针,就可以直接写成常方法  2.如果成员方法内部不需要改动成员,但是会对外暴露成员引用或者指针,就写两个成员方法(const方法和非const方法),形成重载   3.如果成员方法内部需要改动成员,就写成普通函数
class Person
{
private:
	int _age;
	int _sex;
	char* _name; 
public:
	
	Person()
	{
		cout << "Person()" << endl;
	}
	Person(int age)
	{
		cout << "Person(int age)" << endl;
		_age = age;
		_name = NULL;
	}

	Person(const char* name, int age, int sex)
	{
		_age = age;
		_sex = sex;
		_name = new char[strlen(name) + 1];
		memset(_name, 0, strlen(name) + 1);
		for (int i = 0; i < strlen(name); i++)
		{
			_name[i] = name[i];
		}
	}
	int get_age()//Person* const this
	{
		return _age;
	}
	void set_age(int age)
	{
		_age = age;
	}
	~Person()
	{
		cout << "~Person" << endl;
		delete[]_name;
	}
};

int main()
{
	const Person p1("xiaohua", 18, 0);//p1是一个常量
	cout << p1.get_age() << endl;//调用出问题
	cout << p1.set_age() << endl;//调用出问题
	//为什么会出问题?
	//因为参数列表不匹配,this指针不匹配
	//函数的第一个参数为 Person* const this ,this指针是个常量
	//指向p1的指针是Person const *p = &p1;对象是个常量
	//将常量的地址给了一个非常量的指针,暴露了常量的地址
	return 0;
}

解决方案如下:

int get_age()//Person* const this --->Person const * const this,
{            //解决方案是多加一个const,即让this指针指向的内容不可改变
		     //如何加又是一个问题?
	return _age;
}

//加const之后叫常方法
int get_age()const  //将const加在后边就等价于Person const * const this
{                   //还有一个引申出的问题是普通的对象可以调用常方法吗?可以,将一个非常量地址给一个常量指针是可以的,相当于安全性增加
	return _age;
}
int get_age()const  //常方法中不能调用普通函数,因为调用普通函数传入的类型为常方法中this的类型
{           
	set_age(10);  //this->set_age(10); 常对象是不能调用普通函数的,又会出现上述那种情况,将一个常指针给一个普通指针   
	return _age;
}
void set_age(int age)
{
	_age = age;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值