相比較私有繼承與包含來說,一般情況下應使用包含關系來建立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;
}
程式運作結果如下圖:
