继承关系中赋值运算符的重载
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;
}
单例模式在多进程和多线程时可能会发生线程安全的问题。