相比较私有继承与包含来说,一般情况下应使用包含关系来建立has-a关系,如果新类需要访问原有类的保护成员,或者重新定义原有类的虚函数成员,则应当使用私有继承。
对于保护派生和私有派生,基类的共有成员将会变为保护成员或者私有成员,假设要使得基类方法在派生类外可用,我们可以拓展基类方法的访问权限。主要有两种方法:
1.重新在派生类中定义要使用的基类方法。
比如要在派生类student中使用valarray<double>的sum()方法,可以在派生类公有部分重新定义sum()方法。
double student::sum() const
{
return valarray<double>::sum();
}
2.利用using重新定义访问权限
可以在派生类公有部分声明
class student:private string,private valarray<double>
{
private:
....
public:
using valarray<double>::min;
using valarray<double>::max;//注意不加(),也没有返回值和参数列表
using valarray<couble>::operator[];
}
因此,可以直接在类外使用
student stu;
....
cout<<stu.max()<<endl;
下面的例子私有继承在继承类中通过对this指针的强制类型转换来访问基类的数据成员,通过基类名+作用域解析运算符::来访问基类的方法。测试程序与C++中的代码重用(一)相同
//statement.h
#ifndef _STATEMENT_H_
#define _STATEMENT_H_
#include<iostream>
#include<string>
#include<valarray>//包含size(),max(),min(),sum(),operator[](int i)
//定义包含关系
using namespace std;
class student:private string,private valarray<double>//合并valarray和string类
{
private:
typedef valarray<double> Arraydb;
/*string name;
Arraydb score;*/
ostream& arr_out(ostream &os) const;
public:
student() :string("null"), Arraydb(){}
explicit student(int i) :string("null"), Arraydb(i){}
student(const char *c, const double *pt, int n) :string(c), Arraydb(pt, n){}
explicit student(const string &str) :string(str), Arraydb(){}
student(const string &str, int n, const double &d) :string(str), Arraydb(n, d){}
student(const student &stu);
~student(){}
const string& get_name()const;
void show(ostream &os)const;
const double operator[](int i) const{ return Arraydb::operator[](i); }
double& operator[](int i){ return Arraydb::operator[](i); }//以便于输入数据
double average() const;
friend istream& getline(istream &is, student &stu);
friend istream & operator >>(istream &is, student &stu);
friend ostream & operator<<(ostream &os, student &stu);
};
#endif //_STATEMENT_H_
//define.cpp
#include"statement.h"
using namespace std;
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) << " ";//针对基类valarray<double>调用方法double& operator[](int i)const
if (i % 5 == 4)
os << endl;
}
if (i % 5 != 0)
os << endl;
}
else
os << "empty array!";
return os;
}
student::student(const student &stu)//后面main.cpp验证复制构造函数结果
{
(string &)*this = (const string &)stu;
(Arraydb &)*this = (const Arraydb &)stu;
}
const string& student::get_name()const
{
return (const string&)*this;//访问基类对象需要用到强制转换
}
double student::average() const
{
if (Arraydb::size() > 0) //访问基类方法需要用到域名解析符::
return (double)Arraydb::sum() / Arraydb::size();
else
return 0;
}
void student::show(ostream &os)const
{
os << "Scores for " << (const string &)*this<< ":\n";
arr_out(os);
os << "Average is " << average() << endl;
}
istream& getline(istream &is, student &stu)
{
getline(is, (string &)stu);
return is;
}
istream & operator >>(istream &is, student &stu)
{
is >> (string &)stu;
return is;
}
ostream & operator<<(ostream &os, student &stu)
{
os << "Scores for " << (const string &)stu << ":\n";
stu.arr_out(os);
return os;
}
//main.cpp
#include<iostream>
#include<cstdlib>
#include"windows.h"
#include"statement.h"
using namespace std;
void set(student &stu, int n);
const int pupils = 3;
const int quizzes = 5;
int main()
{
student stu[pupils] = { student(quizzes), student(quizzes), student(quizzes) };
cout << "Set infomation for student.\n";
for (int j = 0; j < pupils; j++)
set(stu[j], quizzes);
cout << "The follow content is information for student: ";
for (int j = 0; j < pupils; j++)
cout << stu[j].get_name() << ",";
cout << ".\n";
for (int t = 0; t < pupils; t++)
{
stu[t].show(cout);
}
student temp = student(stu[0]);
cout << "Test for student temp = student(stu[0]), the result for temp as follows.\n";
temp.show(cout);
system("pause");
return 0;
}
void set(student &stu, int n)
{
cout << "please input Student'name: ";
getline(cin, stu);
cout << "please input " << n << " quizzes'score: ";
for (int i = 0; i < n; i++)
cin >> stu[i];
while (cin.get() != '\n')
continue;
}
程序运行结果如下图:
