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){},当然这种写法在非虚基类是属于语法错误的。

posted @ 2018-04-02 23:06  h_hg  阅读(237)  评论(0编辑  收藏  举报