0
点赞
收藏
分享

微信扫一扫

C++之继承<2>【详解】

有点d伤 2023-10-21 阅读 32

C++之继承<2>【详解】

1. 派生类的默认成员函数

1.1 1. 构造成员函数

  无论是否显示的调用基类的构造成员函数,都会自动调用基类的默认成员函数:

#include <iostream>
using namespace std;
class Person
{
public:
	Person(const char* name = "peter")
		: _name(name)
	{
		cout << "Person()" << endl;
	}
	
	string _name; 
};


class Student : public Person
{
public:
	Student(const char* name, int num)
		: _num(num)
	{
		cout << "Student()" << endl;
	}
protected:
	int _num; 
};
int main()
{
	Student s1("jack", 18);
	return 0;
}

没有显示调用
显示调用后:
在这里插入图片描述

上述的后半段的意义是:如果基类没有默认的构造函数,那么是这样的:

	Person(const char* name = "peter")
		: _name(name)
	{}

  可以进行传参来构造对象,如果你在派生类没有显示的调用它,那么不能进行进行传参来构造。

#include <iostream>
using namespace std;

class Person
{
public:
	Person(const char* name = "peter")
		: _name(name)
	{
		cout << "Person()" << endl;
	}
	
	string _name; 
};


class Student : public Person
{
public:
	Student(const char* name, int num)
		: _num(num)
	{
		cout << "Student()" << endl;
	}
protected:
	int _num; 
};
int main()
{
	Student s1("jack", 18);	
	cout << s1._name; 
	return 0;
}

在这里插入图片描述
上图可以看到,传入的参数是“jack”, 但是构造出来的对象属性是“peter”。
  至于必须在初始化列表显示的调用,是因为祖师爷定下的规则是,先构造基类再构造派生类,初始化列表是先于构造函数执行的。
  Person(name)在初始化列表中的顺序可以随意改动的,因为初始化列表的执行顺序只跟声明的顺序有关,跟初始化列表中的先后顺序无关。

1.2 拷贝复制

分别是拷贝构造函数和operator=复制函数:

上面两条的原因和构造函数的一样,就不在赘述。
下面是验证的代码:

#include <iostream>
using namespace std;

class Person
{
public:
	Person(const char* name = "peter")
		: _name(name)
	{
		cout << "Person()" << endl;
	}
	Person(const Person& p)
		: _name(p._name)
	{
		cout << "Person(const Person& p)" << endl;
	}
	Person& operator=(const Person& p)
	{
		cout << "Person operator=(const Person& p)" << endl;
		if (this != &p)//防止复制相同的对象,相同的就不必进行下面步骤了
			_name = p._name;
		return *this;
	}
protected:
	string _name; // 姓名
};



class Student : public Person
{
public:
	Student(const char* name, int num)
		: Person(name)
		, _num(num)
	{
		cout << "Student()" << endl;
	}
	Student(const Student& s)
		: Person(s)
		, _num(s._num)
	{
		cout << "Student(const Student& s)" << endl;
	}

	
	Student& operator = (const Student& s)
	{
		cout << "Student& operator= (const Student& s)" << endl;
		if (this != &s)//防止复制相同的对象,相同的就不必进行下面步骤了
		{
			Person::operator =(s);
			_num = s._num;
		}
		return *this;
	}
protected:
	int _num; //学号
};
int main()
{
	Student s1("jack", 18);
	Student s2(s1);
	return 0;
}

1.3 构造函数和析构函数的执行顺序

  • 首先,为什么一定先调用基类构造函数再调用派生类的的构造函数呢?
      如果你先调用派生类的构造函数,派生类是继承基类的,那么派生类中就可以使用基类中的属性和行为,但是此时还没有调用基类的构造函数,所以不能这样。

  • 为什么一定先调用派生类的析构函数再调用基类的析构函数呢?
      如果先调用基类的析构函数的话,会释放掉一些变量或指针,那么派生类使用继承过来的这些变量或者指针的时候,它们已经变成了野指针,因此不能如此。

在这里插入图片描述

下面是完整代码,大家可以尝试验证:

#include <iostream>
using namespace std;

class Person
{
public:
	Person(const char* name = "peter")
		: _name(name)
	{
		cout << "Person()" << endl;
	}
	Person(const Person& p)
		: _name(p._name)
	{
		cout << "Person(const Person& p)" << endl;
	}
	Person& operator=(const Person& p)
	{
		cout << "Person operator=(const Person& p)" << endl;
		if (this != &p)
			_name = p._name;
		return *this;
	}
	~Person()
	{
		cout << "~Person()" << endl;
	}
protected:
	string _name; // 姓名
};



class Student : public Person
{
public:
	Student(const char* name, int num)
		: Person(name)
		, _num(num)
	{
		cout << "Student()" << endl;
	}
	Student(const Student& s)
		: Person(s)
		, _num(s._num)
	{
		cout << "Student(const Student& s)" << endl;
	}

	
	Student& operator = (const Student& s)
	{
		cout << "Student& operator= (const Student& s)" << endl;
		if (this != &s)
		{
			Person::operator =(s);
			_num = s._num;
		}
		return *this;
	}

	
	~Student()
	{
		cout << "~Student()" << endl;
	}
protected:
	int _num; //学号
};
int main()
{
	Student s1("jack", 18);
	Student s2(s1);
	Student s3("rose", 17);
	s1 = s3;
	return 0;
}

2. 继承和友元

#include <iostream>
using namespace std;

class Student;
class Person
{
public:
	friend void Display(const Person& p, const Student& s);
protected:
	string _name = "zhangsan"; // 姓名
};



class Student : public Person
{
public:
	
protected:
	int _num; //学号
};

void Display(const Person& p, const Student& s)
{
	cout << p._name << endl;
	cout << s._num << endl;
}
int main()
{
	Student s;
	Person p;
	Display(p, s);
	return 0;
}

在这里插入图片描述

从上面图中可以看出。

3. 继承与静态成员

#include <iostream>
#include <string>
using namespace std;


class Person
{
public:
	Person()
	{
		++_count;
		++age;
	}


public:
	static int _count;
	int  age = 0; // 姓名
};
int Person::_count = 0;


class Student : public Person
{
public:

protected:
	int _num; //学号
};

int main()
{
	Student s;
	Person p;
	cout << "Person::_count:  "<<Person::_count<<endl;
	cout << "Person::age:  "<<p.age<<endl;
	return 0;
}

运行结果是:
在这里插入图片描述

  由此可见,静态成员_count是共有的,只有一个。


举报

相关推荐

0 条评论