携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
一、继承中的赋值重载
✔ 测试用例一:
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(const char* name = "dancebit")
: _name(name)
{
cout << "Person(const char* name = \"dancebit\")" << endl;
}
Person(const Person& p)
: _name(p._name)
{
cout << "Person(const Person& p)" << endl;
}
Person& operator=(const Person& p)
{
cout << "Person& operator=(cconst Person& p)" << endl;
if (this != &p)
_name = p._name;
return *this;
}
~Person()
{
cout << "~Person()" << endl;
}
protected:
string _name;
int a;
};
class Student : public Person
{
public:
Student(const char* name, int id, const char* address)
: Person(name)
, _id(id)
, _address(address)
{}
Student& operator=(const Student& s)
{
if (this != &s)
{
_id = s._id;
_address = s._address;
//operator=(s);//切片行为,err
Person::operator=(s);//切片行为
}
return *this;
}
private:
int _id;
string _address;
};
int main()
{
Student s1("DANCEBIT", 1, "贵阳市");
Student s2("DanceBit", 2, "北京市");
s1 = s2;
return 0;
}
-
对于子类的赋值重载,我们不写,编译器会默认生成。我们都知道赋值重载和拷贝构造很类似,它针对 a) 内置类型成员完成赋值重载; b) 自定义类型成员,调用它的赋值重载; c) 继承的父类成员作为一个整体,调用父类的赋值重载;
对于子类的赋值重载,默认生成的也够用了。但涉及深浅拷贝问题时就需要自己写。
-
如果显示的在子类中写拷贝赋值,父类部分只能使用切片,但是我们发现出现死循环最后导致栈溢出了,原因是父子类有同名的成员函数 operator=,构成隐藏关系,所以我们上面说 C++ 不敢设计成同名成员函数就报错,这里就可以看到场景了,所以这里的解决方法是指定父类的域。如果子类中的拷贝赋值不显示调用父类的拷贝赋值,便不会调用,此时赋值是不完整的。
我们之前说 double d = 1.1,int i = d,它们是相近类型,完成隐式类型转换,而这里为什么子类对象给父类对象这样的一个切片行为是一种天然行为,不存在类型转换 ❓
两者不能混淆的原因是,如果存在类型转换,其中会产生临时变量 (d ➡ 临时变量 ➡ i),也就意味着 int& i = d 是不行的,const int& i = d 是行的,因为 d 具有常性;而后者如果理解成存在隐式类型转换,Person& ref = s 那么 ref 引用的就是临时变量,但是我们期望的并不是引用临时变量,而是引用或指针指向的是子类对象当中切割出来的父类的那一部分,所以后者是一种天然行为。
二、继承与静态成员
✔ 测试用例二:
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person() { ++_count; }
protected:
string _name;
public:
static int _count;
};
int Person::_count = 0;
class Student : public Person
{
protected:
int _stuNum;
};
class Graduate : public Student
{
protected:
string _seminarCourse;
};
int main()
{
Student s1;
Student s2;
Student s3;
Graduate s4;
cout << "人数:" << Person::_count << endl;
Student::_count = 0;
cout << "人数:" << Person::_count << endl;
cout << "人数:" << Student::_count << endl;
cout << "人数:" << Graduate::_count << endl;
cout << "人数:" << s1._count << endl;
cout << "人数:" << s4._count << endl;
return 0;
}
- 基类定义了 static 静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个 static 成员实例 。
- 基类的静态成员是属于整个继承体系的类,属于这些类的所有对象。