六、继承(二)
1 继承与友元
如果一个基类中存在友元关系,那么这个友元关系能不能继承呢?
例:
#include <iostream>
using namespace std;
class Student;
class Person
{
public:
friend void Display(const Person& p, const Student& s);
protected:
string _name = "张三"; // 姓名
};
class Student : public Person
{
protected:
int _stuNum = 12345678; // 学号
};
void Display(const Person& p, const Student& s)
{
cout << p._name << endl;
cout << s._stuNum << endl;//访问派生类Student的成员_stuNum
}
int main()
{
Person p;
Student s;
Display(p, s);
return 0;
}
运行结果:
从运行结果可以看到,友元关系不能继承,也就是说基类友元不能访问派生类的私有和保护成员。
如果要让基类友元访问派生类的私有和保护成员,需要在派生类中也进行声明。
例:
#include <iostream>
using namespace std;
class Student;
class Person
{
public:
friend void Display(const Person& p, const Student& s);
protected:
string _name = "张三"; // 姓名
};
class Student : public Person
{
public:
friend void Display(const Person& p, const Student& s);
protected:
int _stuNum = 12345678; // 学号
};
void Display(const Person& p, const Student& s)
{
cout << p._name << endl;
cout << s._stuNum << endl;
}
int main()
{
Person p;
Student s;
Display(p, s);
return 0;
}
运行结果:
2 继承与静态成员
如果一个基类中有存在静态成员,那么在派生类中是怎么继承的呢?
例:
#include <iostream>
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()
{
Person p;
Student s;
Graduate g;
cout << &(p._count) << endl;
cout << &(s._count) << endl;
cout << &(g._count) << endl;
cout << "人数:" << Person::_count << endl;
cout << "人数:" << Student::_count << endl;
cout << "人数:" << Graduate::_count << endl;
return 0;
}
运行结果:
从运行结果可以看到,不管是基类还是派生类,静态成员_count
的地址都是一样的,而且不管是基类还是派生类都可以对它进行访问,也就是说当基类定义了static
静态成员,那么整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static
成员实例。
如果我们想实现一个不能被继承的类,该怎么做呢?
实际上,我们可以将类的构造和析构函数设为私有:
#include <iostream>
using namespace std;
class A
{
private:
A()
{}
//~A()
//{}
};
class B :public A
{};
int main()
{
B bb;
return 0;
}
将构造函数设为私有的运行结果:
将析构函数设为私有的运行结果:
但如果这样的话,当我们想定义一个A
类的对象时,也将调用不到它的构造和析构函数,那该怎么办呢?
要解决这个问题,我们就可以在A
中定义一个可以静态成员函数让它来调用私有的构造函数从而实现创建对象。
#include <iostream>
using namespace std;
class A
{
public:
static A CreatObj()
{
return A();
}
private:
A()
{}
};
class B :public A
{};
int main()
{
A::CreatObj();
return 0;
}
运行结果:
这样一来,就可以实现一个不能被继承同时又不影响创建自己对象的类了。