{C++系列} C++基础 day08 操作符重载,继承(向上造型,向下造型)
in C/C++ with 0 comment

{C++系列} C++基础 day08 操作符重载,继承(向上造型,向下造型)

in C/C++ with 0 comment

#复习

========================

二十 # 操作符重载

4# 函数操作符: ()

功能:让对象当做函数来调用

注:对参数个数、类型没有任何限制的操作符重载函数

 class A{};
 A a;
 a(100,200)==>a.operator()(100,200)

#举例

函数操作符重载

#include <iostream>
using namespace std;
class Square{
public:
    double operator()(double x)const{
        return x*x;
    }
    int operator()(int a,int b,int c=9)const{
        return a+b-c;
    }
};
int main(void)
{
    Square square;
    //square.operator()(3.14)
    cout << square(3.14) << endl;
    cout << square(10,40,20) << endl;//30
    cout << square(10,40) << endl;//41
    return 0;
}

5# 下标操作符 []

功能:让对象当做数组去使用

注:非常对象返回左值,常对象返回右值

eg:
string s = "hello"; 
//s.operator[](0)
cout << s[0] << endl;//'h'
s[0] = 'H';//s[0]返回左值
const string s2 = s;
s2[0] = 'H';//error,s2[0]返回右值

#举例

下标操作符重载

#include <iostream>
using namespace std;
//Array表示一个容器类,里面可以存放若干个int
class Array{
public:
    Array(size_t size)
        :m_data(new int[size]),m_size(size){}
    ~Array(void){
        delete[] m_data;
        m_data = NULL;
    }
    //对应非常对象,返回左值
    int& operator[](size_t i){
        return m_data[i];
    }
    //对应常对象,返回右值
    int operator[](size_t i)const{
        return m_data[i];
    }
private:
    int* m_data;
    size_t m_size;
};
int main(void)
{
    Array a(10);
    //a.operator[](0)
    a[0] = 123;
    cout << a[0] << endl;//123
    const Array& ra = a;
    //ra[0] = 321;//error
    return 0;
}

6# new/delete操作符

static void* operator new(size_t size){...}
static void operator delete(void* p){...}

#举例

#include <iostream>
#include <cstdlib>
using namespace std;
class A{
public:
    A(void){cout << "A::A()"<<endl;}
    ~A(void){cout << "A::~A()"<<endl;}
    static void* operator new(size_t size){
        cout << "A::new" << endl;
        void *pv = malloc(size);
        return pv;
    }
    static void operator delete(void* pv){
        cout << "A::delete" << endl;
        free(pv);
    }
};
int main(void)
{
    //1)A* pa = (A*)A::operator new(sizeof(A));
    //2)pa->A::A()
    A* pa = new A;
    //1)pa->A::~A()
    //2)A::operator delete(pa);
    delete pa;
    return 0;

}

7 #类型转换操作符//了解

功能:实现自定义类型转换,将源类型转换为目标类型。

class 源类型{
  operator 目标类型(void)const{...}
}
eg:
Integer i;
i = 100;//int-->Integer
int i2;
i2 = i;//Integer-->int

#举例

类型转换操作符重载

#include <iostream>
using namespace std;

class Integer{
public:
    Integer(void):m_data(0){}
    //int->Integer
    Integer(int data):m_data(data){
        cout << "类型转换构造函数" << endl;
    }
    //Integer->int
    operator int(void)const{
        cout << "类型转换操作符函数" << endl;
        return m_data;
    }
private:
    int m_data;
};
int main(void)
{
    Integer i1;
    i1 = 100;//int-->Integer
    cout << i1 << endl;//100,Integer-->int
    int i2 = i1;//Integer-->int
    cout << i2 << endl;//100
    return 0;
}

8 # 操作符重载限制

1)#不是所有操作符都能重载,下面操作符不能重载

2)#如果一个操作符涉及的操作数都是基本类型,则无法重载。

3)#操作符重载不会改变预定义的优先级

4)#操作符重载无法改变操作数的个数,函数操作符()例外。

5)#无法通过操作符重载发明新的操作符

6)#只能用成员形式不能使用全局形式操作符

=、()、[]、->

==========================

二十一 # 继承(Inheritance)

1 #继承的概念

通过一种机制表达类型之间共性和特性的方式,利用已有的数据类型来定义新的数据类型,这种机制称为继承。

人类:姓名、年龄、吃饭、睡觉
学生类:姓名、年龄、吃饭、睡觉、学号、学习
教师类:姓名、年龄、吃饭、睡觉、工资、讲课

-------------

  人类:姓名、年龄、吃饭、睡觉
  学生类继承人类:学号、学习
  教师类继承人类:工资、讲课
  
    人类(基类/父类)
   /    \
学生类  教师类(子类/派生类)

2 # 继承的语法

class 子类
    :继承方式1 基类1,继承方式2 基类2..{};

继承方式:
  --》公有继承:public
  --》保护继承:protected
  --》私有继承:private
eg:
  class Human{
      姓名、年龄、吃饭、睡觉
  };
  class Student:public Human{
    Student继承了Human类,这时在Student类中
    会存在一份Human类的成员。
  };

《案例》使用继承语法,描述人类、学生类和教师类

3 #公有继承的特性(public)

1)子类对象可以当做基类对象来使用

注:子类对象中包含基类的部分称为“基类子对象”

2)向上造型(重点掌握)

将子类类型指针或引用转换为基类类型的指针或引用。
这种操作性缩小的类型转换,在编译器看来是安全的,可以隐式完成转换。

    class A{};//基类
    class B:public A{};//子类
    B b;
    A* pa = &b;//向上造型
    A& ra = b;//向上造型
    ----------
    void func(A* pa){...}
    func(&b);//向上造型
    -----------
    void func(A& ra){...}
    func(b);//向上造型

inher.JPG

3)向下造型//了解

将基类类型指针或引用转换为子类类型的指针或 引用。
这种操作性放大的类型转换在编译器看来是危险的,不能隐式转换,只能显示转换。

inher2.JPG

4)#子类继承基类的成员

class 子类:public 基类{
   子类(..):基类(实参){}
};

#举例

继承

#include <iostream>
using namespace std;
//人类(基类)
class Human{
public:
    Human(const string& name,int age):
        m_name(name),m_age(age),m_id(1234){}
    void eat(const string& food){
        cout << "我在吃" << food << endl;
    }
    void sleep(int hour){
        cout << "我睡了" << hour << "小时" << endl;
    }
protected://保护成员可以在子类中被访问
    string m_name;
    int m_age;
    //基类的私有成员子类继承后不能直接访问,但是
    //可以提供接口函数间接访问。
    int getID(void){
        return m_id;
    }
private:
    int m_id;
};
//学生类(人类的子类)
class Student:public Human{
public:
    //Human(name,age):说明对基类部分成员的初始化方式
    Student(const string& name,int age,int no)
        :Human(name,age),m_no(no){}
    void who(void){
        cout << "我叫" << m_name << ",今年" <<
            m_age << "岁,学号是" << m_no << endl;
        cout << "m_id=" << getID() << endl;
    }
    void learn(const string& course){
        cout << "我在学" << course << endl;
    }
private:
    int m_no;
};
//教师类(人类的另一个子类)
class Teacher:public Human{
public:
    Teacher(const string& name,int age,
        double salary)
            :Human(name,age),m_salary(salary){}
    void who(void){
        cout << "我叫" << m_name << ",今年" << 
            m_age <<"岁,工资:"<< m_salary << endl; 
    }
    void teach(const string& course){
        cout << "我在教" << course << endl;
    }
private:
    double m_salary;
};
int main(void)
{
    cout << "size=" << sizeof(Student) << endl;

    Student s("悟空",30,10011);
    s.who();
    s.eat("桃子");
    s.sleep(16);
    s.learn("C++编程");
    Teacher t("唐僧",40,50000.5);
    t.who();
    t.eat("唐僧肉");
    t.sleep(7);
    t.teach("佛法");

    //Student*-->Human*:向上造型
    Human* ph = &s;
    ph->eat("水果");
    ph->sleep(10);
    //ph->learn("C++");//error

    //Human*-->Student*:向下造型(安全)
    //向下造型在编译器看来不安全,需要显式转换
    Student* ps = static_cast<Student*>(ph);
    ps->who();

    Human h("林黛玉",28);
    //向下造型(危险)
    Student* ps2 = static_cast<Student*>(&h);
    ps2->who();

    return 0;
}
Responses