完整目录、平台简介、安装环境及版本:参考《21天学C++ 概览》
十六、高级继承
16.1 包容
一个类的数据成员有可能是另一个类的对象,称之为外层类包含内层类;has-a
- 公有继承:类可以继承接口(纯虚函数),可能还有实现,获得接口的关系是IS-A关系;
- 包容:类可以获得实现(通过内层类对象访问其公有函数),但是不能获得接口,即HAS-A关系;
#include <iostream>
#include <string.h>
using namespace std;
class String
{
public:
// constructors
String();
String(const char *const);
String(const String &);
~String();
// overloaded operators
char & operator[](int offset);
char operator[](int offset) const;
String operator+(const String&);
void operator+=(const String&);
String & operator= (const String &);
// General accessors
int GetLen()const { return itsLen; }
const char * GetString() const { return itsString; }
static int ConstructorCount;
private:
String (int); // private constructor
char * itsString;
unsigned short itsLen;
};
// default constructor creates string of 0 bytes
String::String()
{
itsString = new char[1];
itsString[0] = '\0';
itsLen=0;
cout << "\tDefault string constructor\n";
ConstructorCount++;
}
// private (helper) constructor, used only by
// class methods for creating a new string of
// required size. Null filled.
String::String(int len)
{
itsString = new char[len+1];
for (int i = 0; i<=len; i++)
itsString[i] = '\0';
itsLen=len;
cout << "\tString(int) constructor\n";
ConstructorCount++;
}
// Converts a character array to a String
String::String(const char * const cString)
{
itsLen = strlen(cString);
itsString = new char[itsLen+1];
for (int i = 0; i<itsLen; i++)
itsString[i] = cString[i];
itsString[itsLen]='\0';
cout << "\tString(char*) constructor\n";
ConstructorCount++;
}
// copy constructor
String::String (const String & rhs)
{
itsLen=rhs.GetLen();
itsString = new char[itsLen+1];
for (int i = 0; i<itsLen;i++)
itsString[i] = rhs[i];
itsString[itsLen] = '\0';
cout << "\tString(String&) constructor\n";
ConstructorCount++;
}
// destructor, frees allocated memory
String::~String ()
{
delete [] itsString;
itsLen = 0;
cout << "\tString destructor\n";
}
// operator equals, frees existing memory
// then copies string and size
String& String::operator=(const String & rhs)
{
if (this == &rhs)
return *this;
delete [] itsString;
itsLen=rhs.GetLen();
itsString = new char[itsLen+1];
for (int i = 0; i<itsLen;i++)
itsString[i] = rhs[i];
itsString[itsLen] = '\0';
return *this;
// cout << "\tString operator=\n";
}
//non constant offset operator, returns
// reference to character so it can be
// changed!
char & String::operator[](int offset)
{
if (offset > itsLen)
return itsString[itsLen-1];
else
return itsString[offset];
}
// constant offset operator for use
// on const objects (see copy constructor!)
char String::operator[](int offset) const
{
if (offset > itsLen)
return itsString[itsLen-1];
else
return itsString[offset];
}
// creates a new string by adding current
// string to rhs
String String::operator+(const String& rhs)
{
int totalLen = itsLen + rhs.GetLen();
String temp(totalLen);
int i, j;
for (i = 0; i<itsLen; i++)
temp[i] = itsString[i];
for (j = 0; j<rhs.GetLen(); j++, i++)
temp[i] = rhs[j];
temp[totalLen]='\0';
return temp;
}
// changes current string, returns nothing
void String::operator+=(const String& rhs)
{
unsigned short rhsLen = rhs.GetLen();
unsigned short totalLen = itsLen + rhsLen;
String temp(totalLen);
int i, j;
for (i = 0; i<itsLen; i++)
temp[i] = itsString[i];
for (j = 0; j<rhs.GetLen(); j++, i++)
temp[i] = rhs[i-itsLen];
temp[totalLen]='\0';
*this = temp;
}
int String::ConstructorCount = 0;
#include "MyString.h"
class Employee
{
public:
Employee();
Employee(char *, char *, char *, long);
~Employee();
Employee(const Employee&);
Employee & operator= (const Employee &);
const String & GetFirstName() const
{ return itsFirstName; }
const String & GetLastName() const { return itsLastName; }
const String & GetAddress() const { return itsAddress; }
long GetSalary() const { return itsSalary; }
void SetFirstName(const String & fName)
{ itsFirstName = fName; }
void SetLastName(const String & lName)
{ itsLastName = lName; }
void SetAddress(const String & address)
{ itsAddress = address; }
void SetSalary(long salary) { itsSalary = salary; }
private:
String itsFirstName;
String itsLastName;
String itsAddress;
long itsSalary;
};
Employee::Employee():
itsFirstName(""),
itsLastName(""),
itsAddress(""),
itsSalary(0)
{}
Employee::Employee(char * firstName, char * lastName,
char * address, long salary):
itsFirstName(firstName),
itsLastName(lastName),
itsAddress(address),
itsSalary(salary)
{}
Employee::Employee(const Employee & rhs):
itsFirstName(rhs.GetFirstName()),
itsLastName(rhs.GetLastName()),
itsAddress(rhs.GetAddress()),
itsSalary(rhs.GetSalary())
{}
Employee::~Employee() {}
Employee & Employee::operator= (const Employee & rhs)
{
if (this == &rhs)
return *this;
itsFirstName = rhs.GetFirstName();
itsLastName = rhs.GetLastName();
itsAddress = rhs.GetAddress();
itsSalary = rhs.GetSalary();
return *this;
}
int main(){
Employee Edie("Jane","Doe","1461 Shore Parkway", 20000);
Edie.SetSalary(50000);
String LastName("Levine");
Edie.SetLastName(LastName);//程序结束再析构
Edie.SetFirstName(“Edythe”);//生成临时变量,然后调用赋值构造函数,赋值完成后,被析构
cout << "Name: "<< Edie.GetFirstName().GetString()<< " " << Edie.GetLastName().GetString()<<endl;
cout << "Address: " << Edie.GetAddress().GetString()<<endl;
cout << "Salary: " << Edie.GetSalary()<<endl;
return 0;
}
执行结果如下:
String(char*) constructor
String(char*) constructor
String(char*) constructor
String(char*) constructor
String(char*) constructor
String destructor
Name: Edythe Levine
Address: 1461 Shore Parkway
Salary: 50000
String destructor
String destructor
String destructor
String destructor
请按任意键继续. . .
16.1.2 按值和按引用传递
#include "MyString.h"
class Employee
{
public:
Employee();
Employee(char *, char *, char *, long);
~Employee();
Employee(const Employee&);
Employee & operator= (const Employee &);
const String & GetFirstName() const
{ return itsFirstName; }
const String & GetLastName() const { return itsLastName; }
const String & GetAddress() const { return itsAddress; }
long GetSalary() const { return itsSalary; }
void SetFirstName(const String & fName)
{ itsFirstName = fName; }
void SetLastName(const String & lName)
{ itsLastName = lName; }
void SetAddress(const String & address)
{ itsAddress = address; }
void SetSalary(long salary) { itsSalary = salary; }
private:
String itsFirstName;
String itsLastName;
String itsAddress;
long itsSalary;
};
Employee::Employee():
itsFirstName(""),
itsLastName(""),
itsAddress(""),
itsSalary(0)
{}
Employee::Employee(char * firstName, char * lastName,
char * address, long salary):
itsFirstName(firstName),
itsLastName(lastName),
itsAddress(address),
itsSalary(salary)
{}
Employee::Employee(const Employee & rhs):
itsFirstName(rhs.GetFirstName()),
itsLastName(rhs.GetLastName()),
itsAddress(rhs.GetAddress()),
itsSalary(rhs.GetSalary())
{}
Employee::~Employee() {}
Employee & Employee::operator= (const Employee & rhs)
{
if (this == &rhs)
return *this;
itsFirstName = rhs.GetFirstName();
itsLastName = rhs.GetLastName();
itsAddress = rhs.GetAddress();
itsSalary = rhs.GetSalary();
return *this;
}
void PrintFunc(Employee);
void rPrintFunc(const Employee&);
int main()
{
Employee Edie("Jane","Doe","1461 Shore Parkway", 20000);
Edie.SetSalary(20000);
Edie.SetFirstName("Edythe");
String LastName("Levine");
Edie.SetLastName(LastName);
cout << "Constructor count: " ;
cout << String::ConstructorCount << endl;
rPrintFunc(Edie);
cout << "Constructor count: ";
cout << String::ConstructorCount << endl;
PrintFunc(Edie);
cout << "Constructor count: ";
cout << String::ConstructorCount << endl;
return 0;
}
void PrintFunc (Employee Edie)
{
cout << "Name: ";
cout << Edie.GetFirstName().GetString();
cout << " " << Edie.GetLastName().GetString();
cout << ".\nAddress: ";
cout << Edie.GetAddress().GetString();
cout << ".\nSalary: " ;
cout << Edie.GetSalary();
cout << endl;
}
void rPrintFunc (const Employee& Edie)
{
cout << "Name: ";
cout << Edie.GetFirstName().GetString();
cout << " " << Edie.GetLastName().GetString();
cout << "\nAddress: ";
cout << Edie.GetAddress().GetString();
cout << "\nSalary: " ;
cout << Edie.GetSalary();
cout << endl;
}
执行结果如下:
String(char*) constructor
String(char*) constructor
String(char*) constructor
String(char*) constructor
String destructor
String(char*) constructor
Constructor count: 5
Name: Edythe Levine
Address: 1461 Shore Parkway
Salary: 20000
Constructor count: 5
String(String&) constructor
String(String&) constructor
String(String&) constructor
Name: Edythe Levine.
Address: 1461 Shore Parkway.
Salary: 20000
String destructor
String destructor
String destructor
Constructor count: 8
String destructor
String destructor
String destructor
String destructor
请按任意键继续. . .
16.2 私有继承
所有基本成员变量和函数不管在基类中的实际访问级别如何,均被看作是声明为私有;
私有继承不涉及继承接口,只继承实现(HAS-A关系,类似包容)
- 子类需要通过成员函数访问基类成员变量和成员函数;
#include <iostream>
using namespace std;
class BaseClass{
public:
BaseClass(){}
~BaseClass(){}
//virtual void testInterface() = 0;//has –a关系,
int getImple(){return 3;}//私有继承后,只能被子类的成员函数访问
private:
int iPriVal;
};
class InheriateClass : private BaseClass{
public:
InheriateClass():BaseClass(){};
~InheriateClass(){};
int getVal(){return getImple();}//可以通过成员函数访问基类,继承实现
};
int main(){
InheriateClass inheriateClass;
inheriateClass.getVal();/
//inheriateClass.getImple();
//inheriateClass.testInterface();
}
执行结果如下:
请按任意键继续. . .
- 当使用多个基类时,不建议使用公有继承和私有继承,应使用包容;
- 当基类中的成员不能用于派生类的客户时,不能使用公有继承;
16.3 友元
16.3.1 友元类
- 把私有性成员变量或函数暴露给另外一个类,则须把这个类声明为一个友元。
- 友元关系不可以继承;
- 友元关系不可以互通;
#include <iostream>
using namespace std;
class FriendClass{
public:
friend class TestClass;
FriendClass(){PriVal = 3;}
~FriendClass(){}
int GetVal(){return 2;}
private:
int PriVal;
int GetPriVal(){return 4;}
};
class TestClass{
public:
int getTest(){return friendClass.PriVal;}
int getTest1(){return friendClass.GetVal();}
int getTest2(){return friendClass.GetPriVal();}
private:
FriendClass friendClass;
};
int main(){
TestClass testClass;
cout<<testClass.getTest()<<endl;
cout<<testClass.getTest1()<<endl;
cout<<testClass.getTest2()<<endl;
return 0;
}
执行结果如下:
3
2
4
请按任意键继续. . .
16.3.2 友元函数1
把访问级别不授予整个类,而是授予该类的一两个函数,如1;
#include <iostream>
using namespace std;
class Animal;
void setValue(Animal& , int);
class Animal{
public:
friend void setValue( Animal&, int);
int GetWeight()const { return itsWeight; }
int GetAge() const { return itsAge; }
private:
int itsWeight;
int itsAge;
};
void setValue(Animal& theAnimal, int theWeight)
{
theAnimal.itsWeight = theWeight;
}
int main()
{
Animal peppy;
setValue(peppy,5);
return 0;
}
执行结果如下:
请按任意键继续. . .
16.3.3 友元函数2(常用:重载运算符)
String s1("String One ");
String s2("String Two ");
char *c1 = { "C-String One " } ;
cout << "s1: " << s1.GetString() << endl;
cout << "s2: " << s2.GetString() << endl;
cout << "c1: " << c1 << endl;
String s3 = s1 + s2; //调用String.operator+(const String &);
cout << "s3: " << s3.GetString() << endl;
String s4 = s1 + c1;//调用String.operator+(const char *const)或String.operator+(const String &);
cout << "s4: " << s4.GetString() << endl;
String s5 = c1 + s2;//不能对C字符串调用operator+,编译错误。需要通过friend解决
cout << "s5: " << s5.GetString() << endl;
#include <iostream>
#include <string.h>
using namespace std;
// Rudimentary string class
class String
{
public:
// constructors
String();
String(const char *const);
String(const String &);
~String();
// overloaded operators
char & operator[](int offset);
char operator[](int offset) const;
String operator+(const String&);
String operator+(const char *const);
friend String operator+(const String&, const String&);
void operator+=(const String&);
String & operator= (const String &);
// General accessors
int GetLen()const { return itsLen; }
const char * GetString() const { return itsString; }
private:
String (int); // private constructor
char * itsString;
unsigned short itsLen;
};
// default constructor creates string of 0 bytes
String::String()
{
itsString = new char[1];
itsString[0] = '\0';
itsLen=0;
// cout << "\tDefault string constructor" << endl;
// ConstructorCount++;
}
// private (helper) constructor, used only by
// class methods for creating a new string of
// required size. Null filled.
String::String(int len)
{
itsString = new char[len+1];
for (int i = 0; i<=len; i++)
itsString[i] = '\0';
itsLen=len;
// cout << "\tString(int) constructor" << endl;
// ConstructorCount++;
}
// Converts a character array to a String
String::String(const char * const cString)
{
itsLen = strlen(cString);
itsString = new char[itsLen+1];
for (int i = 0; i<itsLen; i++)
itsString[i] = cString[i];
itsString[itsLen]='\0';
// cout << "\tString(char*) constructor" << endl;
// ConstructorCount++;
}
// copy constructor
String::String (const String & rhs)
{
itsLen=rhs.GetLen();
itsString = new char[itsLen+1];
for (int i = 0; i<itsLen;i++)
itsString[i] = rhs[i];
itsString[itsLen] = '\0';
// cout << "\tString(String&) constructor" << endl;
// ConstructorCount++;
}
// destructor, frees allocated memory
String::~String ()
{
delete [] itsString;
itsLen = 0;
// cout << "\tString destructor" << endl;
}
// operator equals, frees existing memory
// then copies string and size
String& String::operator=(const String & rhs)
{
if (this == &rhs)
return *this;
delete [] itsString;
itsLen=rhs.GetLen();
itsString = new char[itsLen+1];
for (int i = 0; i<itsLen;i++)
itsString[i] = rhs[i];
itsString[itsLen] = '\0';
return *this;
// cout << "\tString operator=" << endl;
}
//non constant offset operator, returns
// reference to character so it can be
// changed!
char & String::operator[](int offset)
{
if (offset > itsLen)
return itsString[itsLen-1];
else
return itsString[offset];
}
// constant offset operator for use
// on const objects (see copy constructor!)
char String::operator[](int offset) const
{
if (offset > itsLen)
return itsString[itsLen-1];
else
return itsString[offset];
}
// creates a new string by adding current
// string to rhs
String String::operator+(const String& rhs)
{
int totalLen = itsLen + rhs.GetLen();
String temp(totalLen);
int i, j;
for (i = 0; i<itsLen; i++)
temp[i] = itsString[i];
for (j = 0, i = itsLen; j<rhs.GetLen(); j++, i++)
temp[i] = rhs[j];
temp[totalLen]='\0';
cout<<"operator + String"<<endl;
return temp;
}
// Converts a character array to a String
String String::operator+(const char * const cString)
{
int totalLen = itsLen + strlen(cString);
String temp(totalLen);
int i, j;
for (i = 0; i<itsLen; i++)
temp[i] = itsString[i];
for (j = 0, i = itsLen; j<strlen(cString); j++, i++)
temp[i] = cString[j];
temp[totalLen]='\0';
cout<<"operator + char*"<<endl;
return temp;
}
// creates a new string by adding
// one string to another
String operator+(const String& lhs, const String& rhs)
{
int totalLen = lhs.GetLen() + rhs.GetLen();
String temp(totalLen);
int i, j;
for (i = 0; i<lhs.GetLen(); i++)
temp[i] = lhs[i];
for (j = 0, i = lhs.GetLen(); j<rhs.GetLen(); j++, i++)
temp[i] = rhs[j];
temp[totalLen]='\0';
cout<<"operator + friend"<<endl;
return temp;
}
int main()
{
String s1("String One ");
String s2("String Two ");
char *c1 = { "C-String One " } ;
String s3;
String s4;
String s5;
cout << "s1: " << s1.GetString() << endl;
cout << "s2: " << s2.GetString() << endl;
cout << "c1: " << c1 << endl;
s3 = s1 + s2;
cout << "s3: " << s3.GetString() << endl;
s4 = s1 + c1;
cout << "s4: " << s4.GetString() << endl;
s5 = c1 + s2;
cout << "s5: " << s5.GetString() << endl;
return 0;
}
执行结果如下:
s1: String One
s2: String Two
c1: C-String One
operator + String
s3: String One String Two
operator + char*
s4: String One C-String One
operator + friend
s5: C-String One String Two
请按任意键继续. . .
16.3.4 重载插入运算符 <<
让String拥有cout功能,即
String theString;
cout<<theString.getString()<<endl; //通常打印串
Cout<<theString<<endl; //重载后打印串
#include <iostream>
#include <string.h>
using namespace std;
class String
{
public:
// constructors
String();
String(const char *const);
String(const String &);
~String();
// overloaded operators
char & operator[](int offset);
char operator[](int offset) const;
String operator+(const String&);
void operator+=(const String&);
String & operator= (const String &);
friend ostream& operator<<
( ostream& theStream,String& theString);
// General accessors
int GetLen()const { return itsLen; }
const char * GetString() const { return itsString; }
private:
String (int); // private constructor
char * itsString;
unsigned short itsLen;
};
// default constructor creates string of 0 bytes
String::String()
{
itsString = new char[1];
itsString[0] = '\0';
itsLen=0;
// cout << "\tDefault string constructor" << endl;
// ConstructorCount++;
}
// private (helper) constructor, used only by
// class methods for creating a new string of
// required size. Null filled.
String::String(int len)
{
itsString = new char[len+1];
for (int i = 0; i<=len; i++)
itsString[i] = '\0';
itsLen=len;
// cout << "\tString(int) constructor" << endl;
// ConstructorCount++;
}
// Converts a character array to a String
String::String(const char * const cString)
{
itsLen = strlen(cString);
itsString = new char[itsLen+1];
for (int i = 0; i<itsLen; i++)
itsString[i] = cString[i];
itsString[itsLen]='\0';
// cout << "\tString(char*) constructor" << endl;
// ConstructorCount++;
}
// copy constructor
String::String (const String & rhs)
{
itsLen=rhs.GetLen();
itsString = new char[itsLen+1];
for (int i = 0; i<itsLen;i++)
itsString[i] = rhs[i];
itsString[itsLen] = '\0';
// cout << "\tString(String&) constructor" << endl;
// ConstructorCount++;
}
// destructor, frees allocated memory
String::~String ()
{
delete [] itsString;
itsLen = 0;
// cout << "\tString destructor" << endl;
}
// operator equals, frees existing memory
// then copies string and size
String& String::operator=(const String & rhs)
{
if (this == &rhs)
return *this;
delete [] itsString;
itsLen=rhs.GetLen();
itsString = new char[itsLen+1];
for (int i = 0; i<itsLen;i++)
itsString[i] = rhs[i];
itsString[itsLen] = '\0';
return *this;
// cout << "\tString operator=" << endl;
}
//non constant offset operator, returns
// reference to character so it can be
// changed!
char & String::operator[](int offset)
{
if (offset > itsLen)
return itsString[itsLen-1];
else
return itsString[offset];
}
// constant offset operator for use
// on const objects (see copy constructor!)
char String::operator[](int offset) const
{
if (offset > itsLen)
return itsString[itsLen-1];
else
return itsString[offset];
}
// creates a new string by adding current
// string to rhs
String String::operator+(const String& rhs)
{
int totalLen = itsLen + rhs.GetLen();
String temp(totalLen);
int i, j;
for (i = 0; i<itsLen; i++)
temp[i] = itsString[i];
for (j = 0; j<rhs.GetLen(); j++, i++)
temp[i] = rhs[j];
temp[totalLen]='\0';
return temp;
}
// changes current string, returns nothing
void String::operator+=(const String& rhs)
{
unsigned short rhsLen = rhs.GetLen();
unsigned short totalLen = itsLen + rhsLen;
String temp(totalLen);
int i, j;
for (i = 0; i<itsLen; i++)
temp[i] = itsString[i];
for (j = 0, i = 0; j<rhs.GetLen(); j++, i++)
temp[i] = rhs[i-itsLen];
temp[totalLen]='\0';
*this = temp;
}
// int String::ConstructorCount =
ostream& operator<< ( ostream& theStream,String& theString)
{
theStream << theString.itsString;
return theStream;
}
int main()
{
String theString("Hello world.");
cout << theString;
return 0;
}
执行结果如下:
Hello world.请按任意键继续. . .