C++运算符重载与多继承及二义性详解

 更新时间:2022年11月23日 16:09:38   作者:lpf_wei  
继友元知识过后,就到了今天的C++运算符重载的内容了,运算符重载是C++里比较重要的内容。这篇博文不会一下子讲完各种运算符重载,因为太多了了也不好吸收掌握,所以运算符重载我准备分多次记录和分享,那么接下来进入正文

1.类外运算符重载

class Point {
private:
    int x,y;
public:
    // 系统C++源码,大量使用此方式 :x(x), y(y)
    Point(int x, int y) :x(x), y(y) {}
    // set get 函数
    void setX(int x) {
        this->x = x;
    }
    void setY(int y) {
        this->y = y;
    }
    int getX() {
        return this->x;
    }
    int getY() {
        return this->y;
    }
};
/*类外运算符重载
 * 在真实开发过程中,基本上都是写在类的里面的,外部是不能获取内部的私有成员的
 * */
Point operator + (Point point1,Point point2){
    int x = point1.getX() + point2.getX();
    int y = point1.getY() + point2.getY();

    Point res(x, y);
    return res;
}
int main(){
    Point pointA(10,20);
    Point pointB(10,20);
    Point pointC=pointA+pointB;
    cout << pointC.getX() << " , " << pointC.getY() << endl;
}

日志输出:
20 , 40

两个对象做+法运算就是执行了运算符重载函数

2.类内部运算符号重载

class Point {
private:
    int x,y;
public:
    Point(){}
    // 系统C++源码,大量使用此方式 :x(x), y(y)
    Point(int x, int y) :x(x), y(y) {}
    // set get 函数
    void setX(int x) {
        this->x = x;
    }
    void setY(int y) {
        this->y = y;
    }
    int getX() {
        return this->x;
    }
    int getY() {
        return this->y;
    }
    /*
     * 常量引用:不允许修改,只读模式
     * & 性能的提高,如果没有&  运行+ 构建新的副本,会浪费性能
     * 如果增加了& 引用是给这块内存空间取一个别名而已
     * */
    Point operator + (const Point & point){
        int x=this->x+point.x;
        int y=this->y+point.y;
        return Point(x,y);
    }
    Point operator - (const Point & point){
        int x=this->x-point.x;
        int y=this->y-point.y;
        return Point(x,y);
    }
    void operator ++() { //  ++对象
        this->x = this->x + 1;
        this->y = this->y + 1;
    }
    void operator ++ (int) { // 对象++
        this->x = this->x + 1;
        this->y = this->y + 1;
    }
    /*重载<< 输出运算符号
     * istream 输入 系统的
     * ostream 输出 系统的
     * */
  /*  friend void operator << (ostream & _START,Point &point){
        _START << " 开始输出 " << point.x << " : " << point.y << " 结束了 " << endl;
    }*/
    /*多个<< 连着写 */
  friend ostream & operator << (ostream & _START,Point &point){
      _START << " 开始输出 " << point.x << " : " << point.y << " 结束了 " << endl;
      return _START;
  }
    // istream 输入 系统的
    friend istream & operator >> (istream & _START, Point & point) {
        // 接收用户的输入,把输入的信息
        _START >> point.x >> point.y;
        return _START;
    }
};
int main(){
    Point pointA(30,50);
    Point pointB(10,20);
//    Point pointC=pointA-pointB;
    ++pointA;
//    cout << pointA.getX() << " , " << pointA.getY() << endl;
     cout << pointA << pointB <<endl; // 多个的
    Point pointC;
    cin >> pointC; // >> 是我们自己重载的哦
    cout << "你输入的是:" << pointC.getX() << endl;
    cout << "你输入的是:" << pointC.getY() << endl;
}
  • 类内部运算符重载,允许访问私有变量
  • 传入的参数是常量引用,const 表示不可更改,& 可以提升性能,只会有一个变量别名,不加会拷贝一份,浪费内存。
  • << >> 重载,需要加friend 友元函数来进行重载
  • ostream & _START:表示输出
  • istream & _START:表示输入

3.[] 运算符号重载

class ArrayClass {
private:
    int size =0 ; // 大小  开发过程中,给size赋默认值,不然可能会出现,无穷大的问题
    int * arrayValue; // 数组存放 int 类型的很多值
public:
    ArrayClass(){
        /*指针类型必须分配空间*/
        arrayValue= static_cast<int *>(malloc(sizeof(int *) * 10));
    }
    void set(int index, int value) {
        arrayValue[index] = value; // []目前不是我的
        size+=1;
    }
    int getSize() { // size成员的目标:是为了循环可以遍历
        return this->size;
    }
    // 运算符重载 [index]
    int operator[](int index) {
        return this->arrayValue[index]; // 系统的
    }
};
// 输出容器的内容
void printfArryClass(ArrayClass arrayClass) {
    cout << arrayClass.getSize() << endl;
    for (int i = 0; i < arrayClass.getSize(); ++i) {
        cout << arrayClass[i] << endl; // []是我们自己的 重载符号
    }
}
int main(){
    ArrayClass arrayClass;  // 栈区    实例出来的对象,是在堆区了
    arrayClass.set(0, 100);
    arrayClass.set(1, 200);
    arrayClass.set(2, 300);
    arrayClass.set(3, 400);
    arrayClass.set(4, 500);
    printfArryClass(arrayClass);
}

4.c++继承

class Person {
public:
    char *name;
    int age;
public:
    Person(char *name, int age) : name(name) {
        this->age = age;
        cout << "Person 构造函数" << endl;
    }
    void print() {
        cout << this->name << " , " << this->age << endl;
    }
};
class Student : public Person {
private:
    char * course;
public:
    Student(char * name, int age, char* course) : Person(name, age) , course(course) {
        cout << "Student 构造函数" << endl;
    }
    void test() {
        cout << name << endl;
        cout << age << endl;
        print();
    }
};
  • 默认是 隐式代码: : private Person
  • 私有继承:在子类里面是可以访问父类的成员,但是在类的外面不行
  • 必须公开继承,才可以访问父类的成员
  • 先执行父类的构造函数,再执行子类的构造函数

5.多继承

class BaseActivity1 {
public:
    void onCreate() {
        cout << "BaseActivity1 onCreate" << endl;
    }
    void onStart() {
        cout << "BaseActivity1 onStart" << endl;
    }
    void show() {
        cout << "BaseActivity1 show" << endl;
    }
};
class BaseActivity2 {
public:
    void onCreate() {
        cout << "BaseActivity2 onCreate" << endl;
    }
    void onStart() {
        cout << "BaseActivity2 onStart" << endl;
    }
    void show() {
        cout << "BaseActivity2 show" << endl;
    }
};
// 子类 继承 二个父类
class MainActivity1 : public BaseActivity1, public BaseActivity2{
public:
    void onCreate() {
        cout << "MainActivity1 onCreate" << endl;
    }
    void onStart() {
        cout << "MainActivity1 onStart" << endl;
    }
    void showSonInfo() {
        cout << "MainActivity1 showSonInfo" << endl;
    }
   // void show() {
     //   cout << "MainActivity1 show" << endl;
    //}
};
int main(){
    // 这个是优先寻找子类的函数,因为特别明确,没有问题,还没有产生歧义(二义性)
    MainActivity1 mainActivity1; // 子类
    mainActivity1.onCreate();
    mainActivity1.onStart();
    mainActivity1.showSonInfo();
    // 不明确,二义性,歧义  /*request for member ‘show' is ambiguous*/
//     mainActivity1.show();
    /*解决二义性 通过.来引出父类 然后再调用*/
    mainActivity1.BaseActivity3::show();
    mainActivity1.BaseActivity2::show();
    mainActivity1.BaseActivity1::show();
    // 解决方案二: 子类上 重写父类的show函数
    mainActivity1.show();
}
  • c++ 允许多继承,可能会出现二义性,原则上是尽量避免二义性
  • 通过明确父类的方式解决二义性
  • 通过子类重写父类的方法规避二义性

6.通过虚继承来解决二义性问题

// 祖父类
class Object{
public:
    int number;
    void show() {
        cout << "Object show run..." << endl;
    }
};
// 父类1
class BaseActivity1 : virtual public Object {
};
// 父类2
class BaseActivity2 : virtual public Object {
};
// 子类
class Son : public BaseActivity1, public BaseActivity2 {
};
int main(){
    Object object;
    BaseActivity1 baseActivity1;
    BaseActivity2 baseActivity2;
    Son son;
    object.number = 100;
    baseActivity1.number = 200;
    baseActivity2.number = 300;
    son.number = 400;
    object.show();
    baseActivity1.show();
    baseActivity2.show();
    son.show();
    cout << object.number << endl;
    cout << baseActivity1.number << endl;
    cout << baseActivity2.number << endl;
    cout << son.number << endl;
}
  • 如果没有虚继承,那么son对象访问number就会报二义性的问题,同时访问show方法同样存在二义性问题
  • 由于在继承的时候添加了虚继承,就能解决类似这样的问题,虚继承的含义是:将通过继承得来的number和show方法,放置在另外一个统一空间上,这样子类再访问的时候就不会出现二义性的问题了。

到此这篇关于C++运算符重载与多继承及二义性详解的文章就介绍到这了,更多相关C++运算符重载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • c++11 实现枚举值到枚举名的转换问题

    c++11 实现枚举值到枚举名的转换问题

    这篇文章主要介绍了c++11 实现枚举值到枚举名的转换,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • C语言详解如何应用模拟字符串和内存函数

    C语言详解如何应用模拟字符串和内存函数

    这篇文章主要介绍了C语言详解如何应用模拟字符串和内存函数,文章有点长,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-02-02
  • C语言数组实现学生信息管理系统设计

    C语言数组实现学生信息管理系统设计

    这篇文章主要为大家详细介绍了C语言数组实现学生信息管理系统设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • C语言实例讲解四大循环语句的使用

    C语言实例讲解四大循环语句的使用

    C语言有四大循环语句,他们之间可以进行任意转换。本文将首先对其语法进行讲解,然后通过一个实例用四种循环来实现。相信通过本文的学习,大家都能够对C语言循环语句有着熟练的掌握
    2022-05-05
  • 解析C++多文件编程问题

    解析C++多文件编程问题

    在某些场景中,考虑到编译效率和可移植性,#pragma once 和 #ifndef 经常被结合使用来避免头文件被 重复引入,这里介绍用 _Pragma 操作符避免头文件重复引入的问题,感兴趣的朋友跟随小编一起看看吧
    2021-10-10
  • 关于C++STL string类的介绍及模拟实现

    关于C++STL string类的介绍及模拟实现

    这篇文章主要介绍了关于C++STL string类的介绍及模拟实现的相关资料,需要的朋友可以参考下面具体的文章内容
    2021-09-09
  • 浅析C++中模板的那点事

    浅析C++中模板的那点事

    C++中的模板可分为函数模板和类模板,而把函数模板的具体化称为模板函数,把类模板的具体化成为模板类。下面让我们分别看看什么是函数模板和类模板吧
    2013-09-09
  • C语言静态版通讯录的设计与实现

    C语言静态版通讯录的设计与实现

    静态版通讯录是一种简单的通讯录实现方式,通过定义固定的数组大小来存储联系人信息。该方法不支持动态增删联系人,但具有实现简单、易于理解的优点。在程序设计中,需注意数组边界溢出等问题
    2023-04-04
  • C++中 ‘=default ’及‘ =delete ’的使用

    C++中 ‘=default ’及‘ =delete ’的使用

    这篇文章主要介绍了C++中 =default 及 =delete 使用,使用=default和=delete可以控制编译器默认函数体的使用,下面我们就来看看具体的室友方法吧,需要的朋友也可以参考一下
    2021-12-12
  • C++ Qt实现浏览器网页内嵌的音视频播放器

    C++ Qt实现浏览器网页内嵌的音视频播放器

    这篇文章主要为大家详细介绍了如何利用C++ Qt实现浏览器网页内嵌的音视频播放器,并支持软硬解码,支持音频,支持录像截图,支持多路播放等,感兴趣的可以了解下
    2024-01-01

最新评论