c++继承
继承方式
形式 | public | protected | private |
---|---|---|---|
public继承 | public | protected | 不可见 |
protected继承 | protected | protected | 不可见 |
private继承 | private | private | 不可见 |
注:默认priavte
知识点
- 不可继承的函数:构造函数、拷赋值函数、析构函数
- 虽然一般的运算符可以继承,但一般需要重写
常用方法
让派生类使用基类的友元函数
#include <iostream>
using namespace std;
class base
{
private:
int value = 90;
public:
friend ostream& operator<<(ostream &os,const base &a)
{
os << a.value << endl;
return os;
}
};
class derive:public base
{
private:
int n = 100;
public:
friend ostream& operator<<(ostream &os,const derive &a)
{
os << (const base&)a;//强制转换为基类
os << a.n << endl;
return os;
}
};
派生类的复制函数注意是否需要先复制基类
class base
{};
class derive:public base
{
public:
derive& operator=(const derive &b)
{
if(thie == &b)
return *this;
base::operator=(b);//先复制基类部分
//复制本类
return *this;
}
};
使用using重新定义访问权限
#include <iostream>
#include <valarray>
using namespace std;
class student:private string,private valarray<double>
{
public:
student(const string& s,double* a,int n):string(s),valarray<double>(a,n){}
const string& name()const
{
return (const string &)*this;
}
/* int sum()const
{
return valarray<double>::sum();
} */
using valarray<int>::sum;
};
多继承(MI,Multi Inheritance)
using namespace std;
class Worker
{
private:
string name;
public:
Worker(const string &s):name(s){}
virtual void show()const =0;
};
class Singer:public Worker
{
private:
int voice;
public:
Singer(const string &name,int _voice):Worker(name),voice(_voice){};
virtual void show()const{}
};
class Waiter:public Worker
{
private:
int panache;
public:
Waiter(const string &name,int _panache):Worker(name),panache(_panache){};
virtual void show()const{}
};
class SingingWaiter:public Singer,public Waiter
{
private:
public:
SingingWaiter(const string &name,int _voice,int _panache):Singer(name,_voice),Waiter(name,_panache){}
};
指针易错
SingingWaiter由Singer和Waiter派生,所以它有两个Worker,所以下面代码是错的,因为p指向的Worker不明确。
SingingWaiter sw("name",5,4);
Worker *p = &sw;
正确的写法Worker *p = (Waiter*)&sw;
或Worker *p = (Singer*)&sw;
。
同名方法
由于SingingWaiter继承了来自Singer和Waiter中的show,所以它一共两个show,调用方法如下
SingingWaiter a("name",4,5);
a.show();//wrong
a.Singer::show();//right
a.Waiter::show();//right
或者也可以自己重新定义SingingWaiter的show。
虚基类
虚基类使得多个类派生出的对象只继承一个基类对象。声明如下,让Singer和Waiter变成虚基类,也就是说SingingWorker只有一个Worker对象。
using namespace std;
class Worker
{
private:
string name;
public:
Worker(){}
Worker(const string &s):name(s){}
virtual void show()const =0;
};
class Singer:virtual public Worker
{
private:
int voice;
public:
Singer(const string &name,int _voice):Worker(name),voice(_voice){};
virtual void show()const{}
};
class Waiter:virtual public Worker
{
private:
int panache;
public:
Waiter(const string &name,int _panache):Worker(name),panache(_panache){};
virtual void show()const{}
};
class SingingWaiter:public Singer,public Waiter
{
private:
public:
SingingWaiter(const string &name,int _voice,int _panache):Singer(name,_voice),Waiter(name,_panache){}
};
使用虚基类时,使用的是另一种新的构造方法。当基类是虚时,禁止信息通过中间类传递给基类,也就说,上面的构造函数SingingWaiter中,Singer(name,_voice)和Waiter(name,_panache)中的name不会传递给Worker,此时调用的时Worker的默认构造函数Worker()。
如果需要显示地调用基类的构造函数,可以这样写:SingingWaiter(const string &name,int _voice,int _panache):Worker(name),Singer(name,_voice),Waiter(name,_panache){}
,当然这种写法在非虚基类是属于语法错误的。