c++——私有继承

私有继承:使用私有继承,基类的公有成员和保护成员都将成为派生类的私有成员,只可以在派生类的成员函数中使用
一、私有继承示例

class Student : private std::string,private std::valarray<double>
{
public:
 ...
}
//student以私有继承的方式继承了string类和valarray类
//stduent是多重继承(使用多个基类的继承被称为多重继承)

示例student类

class Student
{
private:
	typedef std::valarray<double> ArrayDb;//可以在student类的实现中使用,类外不可以
	std::string name;
	ArrayDb scores;
	std::ostream & arr_out(std::ostream & os) const;
public:
	Student(): name("NULL Student"),scores() {}

	//explicit 防止单参数的构造函数的隐式转换
	explicit Student(const std::string & s) : name(s),scores() {}  //explicit 表示该构造函数是显示的,只能修饰一个参数的构造函数
	explicit Student(int n) : name("Nully"),scores(n) {}
	Student (const std::string & s,int n) : name(s),scores(n) {}
	Student (const std::string & s,const ArrayDb & a) : name(s),scores(a) {}
	Student (const char * str,const double * pd,int n) : name(str),scores(pd,n) {}
	~Student() {}
	double Average() const;
	const std::string & Name() const;
	double & operator[](int i);
	double operator[](int i) const;

	friend std::istream & operator>>(std::istream & is,Student & stu);//重载输入
	friend std::istream & getline(std::istream & is,Student & stu);
	friend std::ostream & operator<<(std::ostream & os,const Student & stu);//重载输出
};

1.初始化类的区别

公有继承的构造函数初始化
Student(const char *str,const double *pd,int n) : name(str),scores(pd,n){}

私有继承的构造函数初始化
Student(const char * str,const double *pd,int n) :std::string(str),ArrayDb(pd,n){}
[]1.私有继承使用成员初始化列表方法时,使用类名而不是成员名来初始化标识构造函数。
     2.在私有继承中,在不进行显示类型转换的情况下,不能将指向派生类的引用或者指针赋给基类引用或指针。

2.私有继承demon

#include
#include
#include

using std::ostream;
using std::endl;
using std::istream;
using std::string;

class Student : private std::string, private std::valarray<double>
{
private:
	typedef std::valarray<double> ArrayDb;//可以在student类的实现中使用,类外不可以
	std::ostream & arr_out(std::ostream & os) const;
public:
	Student() : std::string("Null student"),ArrayDb() {}
	explicit Student(const std::string & s) : std::string(s),ArrayDb() {}
	explicit Student(int n) : std::string("Nully"),ArrayDb(n) {}
	Student(const std::string & s,int n) : std::string(s),ArrayDb(n) {}
	Student(const char *str,const double *pd,int n) : std::string(str),ArrayDb(pd,n) {}
	~Student() {}
	
	double Average() const;
	double & operator[](int i); //适用于对象
	double operator[](int i) const; //适用于取值
	const std::string & Name() const;

	friend std::istream & operator>>(std::istream & is,Student & stu);
	friend std::istream & getline(std::istream & is,Student & stu);
	friend std::ostream & operator<<(std::ostream & os,const Student & stu);
};

//类的实现
double Student::Average() const
{
	if(ArrayDb::size() > 0)
		return ArrayDb::sum()/ArrayDb::size();
	else
		return 0;
}

const string & Student::Name() const
{
	return (const string &)*this;
}

double & Student::operator[](int i)
{
	return ArrayDb::operator[](i);
}

double Student::operator[](int i) const
{
	return ArrayDb::operator[](i);
}

//私有类函数方法,调整打印格式
ostream & Student::arr_out(ostream & os) const
{
	int i;
	int lim = ArrayDb::size();
	if(lim > 0)
	{
		for(i = 0; i < lim; i++)
		{
			os << ArrayDb::operator[](i) << "	";//对 [] 进行了重载
			if(i % 5 == 4)
				os << endl;
		}
		if( i % 5 != 0)
			os<< endl;
	}
	else
		os << "empty array";
	return os;
}


istream & getline(istream & is,Student & stu)
{
	getline(is,(string &)stu);
	return is;
}

ostream & operator<<(ostream & os,const Student & stu)
{
	os << (const string &)stu <<"同学的成绩:\n";
	stu.arr_out(os);
	return os;
}

using std::cin;
using std::cout;

void set(Student & sa,int n);
const int pupils = 3;
const int quizzes = 5;

int main()
{
	Student ada[pupils] = { Student(quizzes),Student(quizzes),Student(quizzes)};
	int i;
	for (i = 0;i < pupils; ++i)
		set(ada[i],quizzes);
	cout<< "\n Studnet List:\n";

	for(i = 0; i < pupils; ++i)
		cout << ada[i].Name() << endl;
	
	cout << "\n 学生信息:";
	for(i = 0; i < pupils; i++)
	{
		cout << ada[i] <<endl;
		cout << "平均成绩:" << ada[i].Average() << endl;
	}

	cout << " Done\n" << endl;
	return 0;
}

void set(Student & sa,int n)
{
	cout << "请输入学生名:";
	getline(cin,sa);
	cout << "请输入学 " << n <<"项成绩:\n";
	for(int i = 0; i < n; i++)
		cin >> sa[i]; //因为对 & [] 进行了重载,所以这里可以将成绩输入到socres数组中
	while(cin.get() != '\n')
		continue;
}

运行结果:
c++——私有继承_第1张图片
公有继承实现:

#include
#include
#include

class Student
{
private:
	typedef std::valarray<double> ArrayDb;//可以在student类的实现中使用,类外不可以
	std::string name;
	ArrayDb scores;
	std::ostream & arr_out(std::ostream & os) const;
public:
	Student(): name("NULL Student"),scores() {}

	//explicit 防止单参数的构造函数的隐式转换
	explicit Student(const std::string & s) : name(s),scores() {}  //explicit 表示该构造函数是显示的,只能修饰一个参数的构造函数
	explicit Student(int n) : name("Nully"),scores(n) {}
	Student (const std::string & s,int n) : name(s),scores(n) {}
	Student (const std::string & s,const ArrayDb & a) : name(s),scores(a) {}
	Student (const char * str,const double * pd,int n) : name(str),scores(pd,n) {}
	~Student() {}
	double Average() const;
	const std::string & Name() const;
	double & operator[](int i);
	double operator[](int i) const;

	friend std::istream & operator>>(std::istream & is,Student & stu);//重载输入
	friend std::istream & getline(std::istream & is,Student & stu);
	friend std::ostream & operator<<(std::ostream & os,const Student & stu);//重载输出
};


//类的实现
using std::ostream;
using std::endl;
using std::istream;
using std::string;

//平均分
double Student::Average() const
{
	if(scores.size() > 0)
		return scores.sum()/scores.size();
	else
		return 0;
}

const string & Student::Name() const
{
	return name;
}

double & Student::operator[](int i) 
{
	return scores[i];
}

double Student::operator[](int i) const
{
	return scores[i];
}

//私有类函数方法,调整打印格式
ostream & Student::arr_out(ostream & os) const
{
	int i;
	int lim = scores.size();
	if(lim > 0)
	{
		for(i = 0; i < lim; i++)
		{
			os << scores[i] << "	";
			if(i % 5 == 4)
				os << endl;
		}
		if( i % 5 != 0)
			os<< endl;
	}
	else
		os << "empty array";
	return os;
}

istream & operator>>(istream & is,Student & stu)
{
	is >> stu.name;
	return is;
}

istream & getline(istream & is,Student & stu)
{
	getline(is,stu.name);
	return is;
}

ostream & operator<<(ostream & os,const Student & stu)
{
	os << " Scores for " << stu.name << " :\n";
	stu.arr_out(os);
	return os;
}

using std::cin;
using std::cout;

void set(Student & sa,int n);
const int pupils = 3;
const int quizzes = 5;

int main()
{
	Student ada[pupils] = { Student(quizzes),Student(quizzes),Student(quizzes)};
	int i;
	for (i = 0;i < pupils; ++i)
		set(ada[i],quizzes);
	cout<< "\n Studnet List:\n";

	for(i = 0; i < pupils; ++i)
		cout << ada[i].Name() << endl;
	
	cout << "\n 学生信息:";
	for(i = 0; i < pupils; ++i)
	{
		cout << ada[i] <<endl;
		cout << "平均成绩:" << ada[i].Average() << endl;
	}

	cout << " Done\n" << endl;
	return 0;
}

void set(Student & sa,int n)
{
	cout << "请输入学生名:";
	getline(cin,sa);
	cout << "请输入学 " << n <<"项成绩:\n";
	for(int i = 0; i < n; i++)
		cin >> sa[i]; //因为对 [] 进行了重载,所以这里可以将成绩输入到socres数组中
	while(cin.get() != '\n')
		continue;
}

二、保护继承
保护继承:保护继承是私有继承的变体,保护继承在列出基类时使用关键字protected

class Student : protected std::string,protected std::valarray<double>
{...};
//保护继承时,基类的公有成员都将变成派生类的保护成员。和私有继承一样,基类的接口在派生类中也可用,继承层次之外不可用。
//在派生类中,保护继承无需显示类型转换,就可以将基类的指针或引用指向派生类对象。

三、使用using重新定义访问权限
实现:使用派生或私有派生时,基类的公有成员将成为保护成员或私有成员。实现基类的方法在派生类中可用,可以定义一个使用该基类方法的派生类方法。
法一:定义一个使用该基类方法的派生类方法

double Student::sum() const
{
	return std::valarry<double>::sum();
}

法二:将函数调用包装在另一个函数调用中,即使用一个using声明来指出派生类可以使用特定的基类成员,即使用的是私有派生

class Student : private std::string,private std::valarray<double>
{
...
public:
	using std::valarray<double>::min;
	using std::valarray<double>::max;
	...
};


//使用
cout << "high score: " << ada[i].max() << endl;
[]1.using声明只使用成员名——没有圆括号、函数特征标和返回类型。
	 2.using声明只适用于继承,不适用于包含

法三:将方法名放在派生类的公有部分

class Student : private std::string,private std::valarry<double>
{
...
public:
	std::valarry<double>::operator[];//redeclare as public,just use name
}
//法三需要编译器的支持,因为此方法即将摒弃

你可能感兴趣的:(linux——c++,c++,私有继承)