【继承关系中赋值运算符的重载、单例模式】

继承关系中赋值运算符的重载

1.程序设计者在基类和派生类中都没有重载operator=函数; C++编译器将在基类和派生类中自动产生按位赋值的,重载operator=函数;C++编译器会在派生类的重载赋值函数中,加入基类重载赋值函数的调用,是C++编译器合成的代码;(完成行为的统一);// 0 .

2.程序设计者在基类中定义重载赋值函数;而在派生类中没有定义重载赋值函数;C++编译器将会在派生类中自动产生按位赋值的重载赋值函数。并合成代码,调用(关联)基类的重载赋值函数。

class person {
private:

	string _name;
	int _age;
public:
	string _idperson;

	person& operator=(const person& s1)
	{
		_name = s1._name;
		_age = s1._age;
		_idperson = s1._idperson;
		return *this;
	}
	person(const string& idperson, const string& name, int x) : _idperson(idperson), _name(name), _age(x)
	{
		cout << " Create peron" << endl;
	}
};
class Student :public person
{
private:
	string _snum;
	float _score;
public:
	Student(const string& idperson, const string& name, int age, const char* ip) :person(idperson, name, age), _score(100)
	{
		_snum = name;

	}
};
int main()
{
	string name = "wang";
	string idperson{ "22000002" };
	Student stux(idperson, name, 12, "202201");
	Student stux1("931211","lmy",28,"00000");
	stux1 = stux;
	//stux.print();
	stux1.print();
}

在这里插入图片描述

3,程序设计者在基类和派生类中都定义了重载赋值函数;程序设计者在派生类中,没有指定调用基类的重载赋值函数时。C++编译器不会合成调用基类的重载赋值函数的代码。要在派生类的重载赋值函数调用基类的重载赋值函数,程序设计者必须自己加入调用代码。 1 1

class person {
private:

	string _name;
	int _age;
public:
	string _idperson;

	person& operator=(const person& s1)
	{
		_name = s1._name;
		_age = s1._age;
		_idperson = s1._idperson;
		return *this;
	}
	person(const string& idperson, const string& name, int x) : _idperson(idperson), _name(name), _age(x)
	{
		cout << " Create peron" << endl;
	}
};
class Student :public person
{
private:
	string _snum;
	float _score;
public:
	Student(const string& idperson, const string& name, int age, const char* ip) :person(idperson, name, age), _score(100)
	{
		_snum = name;

	}
	Student& operator=(const Student &s1)
	{
		_snum = s1._snum;
		_score = s1._score;
		return *this;
	}
};
int main()
{
	string name = "wang";
	string idperson{ "22000002" };
	Student stux(idperson, name, 12, "202201");
	Student stux1("931211","lmy",28,"00000");
	stux1 = stux;
	//stux.print();
	stux1.print();
}

在这里插入图片描述没有调用基类的赋值重载,那么我们怎么能实现调用基类的赋值重载呢?
请看如下代码:

Student& operator=(const Student &s1)
	{
		_snum = s1._snum;
		_score = s1._score;
		person::operator=( s1);//调动基类的赋值语句
		return *this;
	}

在这里插入图片描述

4.程序设计者在基类中没有定义重载赋值函数(C++编译器将自动产生按位赋值的重载赋值函数)。而在派生类中定义了重载赋值函数。程序设计者在派生类中,没有指定调用基类的重载赋值函数。C++编译器不会合成调用基类的重载赋值函数的代码。

class person {
private:

	string _name;
	int _age;
public:
	string _idperson;
	person(const string& idperson, const string& name, int x) : _idperson(idperson), _name(name), _age(x)
	{
		cout << " Create peron" << endl;
	}
};
class Student :public person
{
private:
	string _snum;
	float _score;
public:
	Student(const string& idperson, const string& name, int age, const char* ip) :person(idperson, name, age), _score(100)
	{
		_snum = name;
	}
	Student& operator=(const Student &s1)
	{
		_snum = s1._snum;
		_score = s1._score;
		//person::operator=( s1);//调动基类的赋值语句
		return *this;
	}
};
int main()
{
	string name = "wang";
	string idperson{ "22000002" };
	Student stux(idperson, name, 12, "202201");
	Student stux1("931211","lmy",28,"00000");
	stux1 = stux;
	//stux.print();
	stux1.print();
}

在这里插入图片描述

//student赋值函数加上这行代码:
		person::operator=( s1);//调动基类的赋值语句
	}

在这里插入图片描述

delete删除关键字用在构造函数上的情况

protected:
	
	lmy(const string& name, const string& sex, int age)  : _name(name), _sex(sex), _age(age) {}
	~lmy() {}
	lmy(const lmy& s1) = delete;//将拷贝构造删除
	lmy& operator=(const lmy& s1) = delete;
	

如果基类的拷贝构造和赋值函数都删除,确在派生类中定义了拷贝和赋值函数,则基类的删除不起作用。

几种域,在类的访问时的一些情况:

在这里插入图片描述
块域:比如if(){}里的内容属于块域。

单例模式

单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)

再说Static 在里面起到的作用:
在这里插入图片描述

第一种单例模式(也是饥汉模式):

using namespace std;
#if 1
class lmy 
{
private:
	string _name;
	string _sex;
	int _age;
public:
	void fun()
	{
		cout << " lmy unique plays  " << endl;
		//_name = "gouzi09";
		cout << "  name =  "<<_name << endl;
	}
protected:
	
	lmy(const string& name, const string& sex, int age)  : _name(name), _sex(sex), _age(age) {}
	~lmy() {}
	lmy(const lmy& s1) = delete;
	//lmy(const lmy& s1) :_name(s1._name), _sex(s1._sex), _age(s1._age) {} 
	lmy& operator=(const lmy& s1) = delete;
	
private:
	static lmy lmy1;
public:
	static lmy& get_single()
	{
		return  lmy1;
	}
};
lmy lmy::lmy1("gouzi2", "man_or_woman", 1);
class llmy :private lmy
{
private:
	string _name;
	string _sex;
	int _age;
public:
	void fun()
	{
		cout << " llmy unique plays  " << endl;
		//lmy::fun();
	}
private:
	
	
	llmy(const string& name, const string& sex, int age) :lmy(name,sex,age),_name(name), _sex(sex), _age(age) {}
	~llmy() {}
	llmy(const llmy& s1)  = delete;
	
	llmy& operator=(const llmy& s1) = delete;
	
private:
	static llmy l1;
public:
	static llmy& get_single()
	{
		return  l1;
	}
};
llmy llmy::l1("gouzi2", "man_or_woman", 1);
int main()
{
	llmy& l1 = llmy::get_single();
	//llmy s1;
	l1.fun();
	lmy& lmy1 = lmy::get_single();
	lmy1.fun();
	//lmy lmy2("gouzi2", "man_or_woman", 1);
	return 0;
}

我们用static 关键字加上私有的构造函数做出了只能构造一个的对像,则称为单例模式。

如果基类的构造函数属性是私有的 ,那么 派生来的单例模式此时无法生成,所以我们可以利用继承特性将其设置成保护:
在这里插入图片描述
在这里插入图片描述
第二种:饿汉模式:实例在使用之前就已经创建。

class lmy 
{
private:
	string _name;
	string _sex;
	int _age;
public:
protected:
	lmy(const string& name, const string& sex, int age)  : _name(name), _sex(sex), _age(age) {}
	~lmy() {}
	lmy(const lmy& s1) = delete;
	//lmy(const lmy& s1) :_name(s1._name), _sex(s1._sex), _age(s1._age) {} 
	lmy& operator=(const lmy& s1) = delete;
	
private:
	static lmy lmy1;
public:
	static lmy& get_single()
	{
		return  lmy1;
	}
};
lmy lmy::lmy1("gouzi2", "man_or_woman", 1);
如果没有继承的情况:在类外定义一个对象,但是成员属性是私有的,构造函数是保护的,所以无法构建对象。
//int main()
//{
//	//lmy& l1 = lmy::get_single();
//	lmy l1("gouzi2", "man_or_woman", 1);
//	//l1.fun();
//
//
//	///llmy& l2 = llmy::get_single();
//	//l2.fun();
//
//	//return 0;
//}
class llmy :private  lmy
{
private:
	string _name;
	string _sex;
	int _age;
public:
public:
	llmy(const string& name, const string& sex, int age) :lmy(name,sex,age),_name(name), _sex(sex), _age(age) {}
	~llmy() {}
	llmy(const llmy& s1)  = delete;
	
	llmy& operator=(const llmy& s1) = delete;
public:
	static llmy& get_single()对于派生类对象,只写了一个get_single函数就只能创建一个对象
	{
		static llmy l1("gouzi2", "man_or_woman", 1);
		return l1;
	}
};
int main()
{
	llmy& l1 = llmy::get_single();
	l1.fun();
	lmy &lmy1 = lmy::get_single();
	return 0;
}

第三种:懒汉模式:实例在使用时才创建。

class lmy 
{
private:
	string _name;
	string _sex;
	int _age;
public:

protected:
	
	lmy(const string& name, const string& sex, int age)  : _name(name), _sex(sex), _age(age) {}
	~lmy() {}
	lmy(const lmy& s1) = delete;
	//lmy(const lmy& s1) :_name(s1._name), _sex(s1._sex), _age(s1._age) {} 
	lmy& operator=(const lmy& s1) = delete;
	
private:
	static lmy lmy1;
public:
	static lmy& get_single()
	{
		return  lmy1;
	}
};
lmy lmy::lmy1("gouzi2", "man_or_woman", 1);
class llmy :private  lmy
{
private:
	string _name;
	string _sex;
	int _age;
public:
public:
	llmy(const string& name, const string& sex, int age) :lmy(name,sex,age),_name(name), _sex(sex), _age(age) {}
	~llmy() {}
	llmy(const llmy& s1)  = delete;
	llmy& operator=(const llmy& s1) = delete;
private :
	static llmy* p;
public:
	static llmy& get_single()
	{
		if (p == nullptr)
		{
			p = new llmy("gouzi2", "man_or_woman", 1);//new 了一个新对象
		}
		return *p;
	}
};
llmy* llmy:: p = nullptr;//注意:llmy* (类型指针)llmy:: (加标识)p(指针变量)
int main()
{
	llmy& l1 = llmy::get_single();
	l1.fun();
	lmy &lmy1 = lmy::get_single();
	lmy1.fun();
	return 0;
}

在这里插入图片描述
单例模式在多进程和多线程时可能会发生线程安全的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值