定义
继承例子
//形式:
class 派生类名:public 基类名
{
};
#include <iostream>
#include <cstring>
using namespace std;
class CStudent
{
private:
string sName;
int nAge;
public:
bool IsThreeGood(){ };//是不是三好学生
void SetName(const string& name)
{
sName=name;
}
};
//未毕业学生派生类,从CStudent派生而来
class CUndergraduateStudent:public CStudent
{
private:
int nDepartment;
//扩充派生类独有的新的成员函数
public:
bool IsThreeGood(){ };//覆盖
//有不同的评判三好学生的标准,可以用同名函数进行覆盖
bool CanBaoYan(){};
};
//已毕业学生派生类
class CGraduatedStudent:public CStudent
{
private:
int nDepartment;
char szMentorName[20];
//系和导师
public:
int CountSalary(){ };
};
派生类对象的内存空间
#include <iostream>
#include <cstring>
using namespace std;
class CStudent
{
private:
string name;
string id;
char gender;//性别,F为女生,M为男生
int age;
public:
void PrintInfo()
{
cout<<name<<" "<<id<<endl;
cout<<gender<<" "<<age<<endl;
}
void SetInfo(const string& name_,const string& id_,int age_,char gender_)
{
name=name_;
id=id_;
age=age_;
gender=gender_;
}
string GetName()
{return name;}
};
class CUndergraduateStudent:public CStudent
{//本科生类,继承了CStudent
private:
string department;//学生所属的系的名称
public:
void QualifiedForBaoYan()
{//给予保研资格
cout<<"qualified for BaoYan"<<endl;
}
void PrintInfo()
{
CStudent::PrintInfo();//调用基类的PrintInfo
//先完成基类的事
cout<<"Department:"<<department<<endl;
//再完成派生类特有的事
}//对基类的修改,表达出派生类对基类的修改
void SetInfo(const string& name_,const string& id_,int age_,char gender_,const string& depaetment_)
{
CStudent::SetInfo(name_,id_,age_,gender_);//调用基类的SetInfo
department=depaetment_;
}//对基类的修改,表达出派生类对基类的修改
};
int main()
{
CUndergraduateStudent s2;
s2.SetInfo("Harry Potter","118829212",19,'M',"Computer Science");
cout<<s2.GetName()<<endl;
s2.QualifiedForBaoYan();
s2.PrintInfo();
return 0;
}
继承关系和复合关系
class CPoint
{
double x,y;
friend class CCircle;
//类的友元化
};
class CCircle
{
double r;
CPoint center;
};
复合关系易错
//小区里养狗管理系统,小区里每个业主最多有十条狗,每条狗只有一个主任
//错误写法
class CDog;
class CMaster
{
CDog dogs[10];
};
class CDog
{
CMaster m;
};
//另一种错误写法:
1.为 狗类 设一个 业主类的成员对象
2.为 业主类 设一个 狗类的对象指针数组
class CDog;
class CMaster
{
CDog* dogs[10];
};
class CDog
{
CMaster m;
};
//凑合的写法:
1.为 狗类 设一个 业主类的对象指针
2.为 业主类 设一个 狗类的对象数组
class CMaster;
class CDog
{
CMaster* pm;
};
class CMaster
{
CDog dogs[10];
};
//正确的写法
为 狗类 设一个 业主类的对象指针
为 业主类 设一个 狗类的对象指针数组
class CMaster;
class CDog
{
CMasetr* pm;
};
class CMaster
{
CDog* dogs[10];
};
覆盖与保护成员
覆盖
#include <iostream>
#include <cstring>
using namespace std;
class base
{
int j;
public:
int i;
void func();
};
class derived:public base
{
public:
int i;
//基类与派生类,同名的函数常见,同名的成员变量是傻子
void access()
{
//j=5;//error
//base::j=5;//error基类的j是private
i=5;//引用的是派生类的i
base::i=5;//引用的是基类的i
func();//派生类的函数
base::func();//基类的函数
}
void func();
};
int main()
{
derived obj;
obj.i=1;//派生类的i
obj.base::i=1;
}
保护成员
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qsz6fvgN-1651671892111)(C:\Users\世界第一可爱\AppData\Roaming\Typora\typora-user-images\image-20220327225328287.png)]
!!!派生类不能访问基类的私有成员
因此有共同的成员变量时,把共同部分设置为保护成员,而不是public成员
#include <iostream>
#include <cstring>
using namespace std;
class Human
{
private:
int nprivate;
public:
int npublic;
protected:
int nprotected;
};
class Man:public Human
{
void AccessFather()
{
npublic=1;
nprivate=1;//error
nprotected=1;//ok,派生类可以访问当前对象基类的protected对象
Man f;
f.nprotected=1;//wrong,f不是当前对象
}
};
派生类的构造函数
#include <iostream>
#include <cstring>
using namespace std;
class Bug
{
private:
int nLegs,nColor;
public:
int nType;
Bug(int nL,int nC):nLegs(nL),nColor(nC){ }
void PrintBug()
{
cout<<nLegs<<" "<<nColor<<endl;
}
};
class FlyBug:public Bug
{
int nWings;
public:
FlyBug(int legs,int color,int wings);
//问题1,派生类不能访问基类的私有成员
};
//错误写法!!!
FlyBug::FlyBug(int legs,int color,int wings)
{
nLegs=legs;//error
nColor=color;//error
nWings=wings;//ok
nType=1;//ok
}
//正确做法:用初始化列表对Bug私有成员进行初始化,调用基类的构造函数
FlyBug::FlyBug(int legs,int color,int wings):Bug(legs,color)
{
nWings=wings;
}
调用基类构造函数的两种方式
-
显性调用
- 在派生类的构造函数中,为基类的构造函数提供参数
FlyBug::FlyBug(int legs,int color,int wings):Bug(legs,color) { nWings=wings; }
-
隐式方式:
- 在派生类的构造函数中,省略基类构造函数时,派生类的构造函数则自动调用基类的默认构造函数(即一个无参构造函数)
包含成员对象的派生类的构造函数写法
#include <iostream>
#include <cstring>
using namespace std;
class Bug
{
private:
int nLegs,nColor;
public:
int nType;
Bug(int nL,int nC):nLegs(nL),nColor(nC){ }
void PrintBug()
{
cout<<nLegs<<" "<<nColor<<endl;
}
};
class Skill
{
public:
Skill(int n){ }
};
class FlyBug:public Bug
{
int nWings;
Skill sk1,sk2;
//每个封闭类对象都要参与初始化
public:
FlyBug(int legs,int color,int wings):Bug(legs,color),sk1(5),sk2(color),nWings(wings){ }
};
公有继承的赋值兼容规则
直接基类和间接基类
#include <iostream>
#include <cstring>
using namespace std;
class Base
{
public:
int n;
Base(int i):n(i)
{
cout<<"Base "<<n<<" constructed"<<endl;
}
~Base()
{
cout<<"Base "<<n<<" destructed"<<endl;
}
};
class Derived:public Base
{
public:
Derived(int i):Base(i)
{
cout<<"Derived constructed"<<endl;
}
~Derived()
{
cout<<"Derived destructed"<<endl;
}
};
class MoreDerived:public Derived
{
public:
MoreDerived(int i):Derived(i)
{
cout<<"MoreDerived constructed"<<endl;
}
~MoreDerived()
{
cout<<"MoreDerived destructed"<<endl;
}
};
int main()
{
MoreDerived obj(1);
return 0;
}
!!!最基类的先构造,最派生的先析构
全面的MyString
class MyString
{
public:
char* p;
MyString(const char* s=NULL)
{
if(s)
{
p=new char[strlen(s)+1];
strcpy(p,s);
}
else
{
p=new char[1];
p[0]='\0';
}
}//初始化值为“”
MyString (const MyString& s)
{
if(s.p)
{
p=new char[strlen(s.p)+1];
strcpy(p,s.p);
}
else
{
p=new char[1];
p[0]='\0';
}
}
~MyString()
{
if(p)
delete[] p;
}
friend ostream& operator<<(ostream& os,const MyString& c)
{
os<<c.p;
return os;
}
MyString& operator=(const char* s)
{
if(p==s)
return *this;
//避免自己赋值自己
if(p)
delete[] p;
if(s)
{
p=new char[strlen(s)+1];
strcpy(p,s);
}
else
{
p=new char[1];
p[0]='\0';
}
return *this;
}
MyString& operator=(const MyString& s)
{
if(p==s.p)
return *this;
if(p)
delete[] p;
if(s.p)
{
p=new char[strlen(s.p)+1];
strcpy(p,s.p);
}
else
{
p=new char[1];
p[0]='\0';
}
return *this;
}
MyString operator+(const MyString& s)
{
char* tmp=new char[strlen(s.p)+strlen(p)+1];
strcpy(tmp,p);
strcat(tmp,s.p);
return MyString(tmp);
}
friend MyString operator+(const char* c,const MyString& s)
{
MyString tmp;
tmp=MyString(c)+s;
return tmp;
}
MyString& operator+(const char* c)
{
*this=*this+MyString(c);
return *this;
}
MyString& operator+=(const char* c)
{
*this=*this+MyString(c);
return *this;
}
friend bool operator<(const MyString& a,const MyString& b)
{
if(strcmp(a.p,b.p)==-1)
return true;
return false;
}
friend bool operator>(const MyString& a,const MyString& b)
{
if(strcmp(a.p,b.p)==1)
return true;
return false;
}
friend bool operator==(const MyString& a,const MyString& b)
{
if(strcmp(a.p,b.p)==0)
return true;
return false;
}
char& operator[] (int i)
{
return p[i];
}
char* operator()(int start,int len)
{
char* tmp=new char[len+1];
for(int i=start;i<start+len;++i)
{
tmp[i-start]=p[i];
}
tmp[len]='\0';
return tmp;
}
};
继承string的MyString
class MyString:public string
{
public:
//构造函数
MyString(const string& p):string(p){ }
MyString(const char* str):string(str){ }
MyString():string(){ }//无参构造函数
//复制构造函数
MyString(const MyString& p):string(p){ }
//重载()
string operator()(int x,int y)
{
return string::substr(x,y);
}
};
注意题
#include <iostream>
using namespace std;
class B {
private:
int nBVal;
public:
void Print()
{ cout << "nBVal="<< nBVal << endl; }
void Fun()
{cout << "B::Fun" << endl; }
B ( int n ) { nBVal = n;}
};
class D:public B
{
private:
int nDVal;
public:
D(int n):B(3*n),nDVal(n){}
//派生类对象,也是一个基类对象
//派生类对象的构造函数,应当在 初始化列表处调用基类的构造函数
void Fun()
{cout<<"D::Fun"<<endl;}
void Print()
{
B::Print();
//就会执行当下对象的基类部分的printf
cout<<"nDVal="<<nDVal<<endl;
}
};
int main() {
B * pb; D * pd;
D d(4); d.Fun();
pb = new B(2); pd = new D(8);
pb -> Fun(); pd->Fun();
pb->Print (); pd->Print ();
pb = & d; pb->Fun();
//!!!这里不是多态,这里基类的指针只能指向派生类中和基类相同的部分
// 因为调用的两个函数都不是虚函数
pb->Print();
return 0;
}