C++面向对象继承与操作符重载

类外运算符重载

cpp 复制代码
// 1.类外运算符重载。

#include <iostream>
using namespace std;

class Derry {
private:
    int x,y;

public:
    // 系统C++源码,大量使用此方式 :x(x), y(y)
    Derry(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;
    }
};

// 在真实开发过程中,基本上都是写在类的里面的,为什么? 娓娓道来  答:外部是不能获取内部的私有成员的
// 把+重载 运算符重载
Derry operator + (Derry derry1, Derry derry2) {
    int x = derry1.getX() + derry2.getX();
    int y = derry1.getY() + derry2.getY();

    Derry res(x, y);
    return res;
}

int main() {
    std::cout << "NDK的第十一节课,同学们大家好" << std::endl;

    // 对象1 + 对象2   C++默认不支持的, Java也不支持,Kotlin也不支持

    // C++/Kotlin 运算符重载 + 把+重载掉

    Derry derry1(1000, 2000);
    Derry derry2(3000, 4000);

    Derry derry = derry1 + derry2; // C++/Java/Kotlin

    cout << derry.getX() << " , " << derry.getY() << endl;

    return 0;
}

类里运算符重载

cpp 复制代码
// 2.类里运算符重载。

#include <iostream>
using namespace std;

class Derry {
private:
    int x,y;

public:
    Derry() {

    }

    // 系统C++源码,大量使用此方式 :x(x), y(y)
    Derry(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() {
        // this->x  -9; 系统怕你在函数里面 修改了
        return this->x;
    }
    int getY() {
        return this->y;
    }

    // +号,运算符重载
    /*Derry operator + (Derry derry1) {
        // this指针 指向当前对象,所以只需要一个
        int x = this->x + derry1.getX();
        int y = this->y + derry1.getY();
        return Derry(x, y);
    }*/

    // 系统是这样写的  常量引用:不允许修改,只读模式
    // const 关键字的解释
    // & 性能的提高,如果没有&  运行+ 构建新的副本,会浪费性能
    // 如果增加了& 引用是给这块内存空间取一个别名而已
    Derry operator + (const Derry& derry1) {
        // this指针 指向当前对象,所以只需要一个
        int x = this->x + derry1.x; // 我在类的里面,是可以拿私有成员的
        int y = this->y + derry1.y; // 我在类的里面,是可以拿私有成员的
        return Derry(x, y);
    }

    // 运算符- 重载
    Derry operator - (const Derry & derry1) {
        int x = this->x - derry1.x;
        int y = this->y - derry1.y;
        return Derry(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, Derry derry1) {
        // 输出换行:<< endl;
        _START << " 单 哥开始输出了 " << derry1.x << " ! " << derry1.y << " 哥结束了 " << endl;
    }

    // 多个的  ostream 输出 系统的
    // 输出 运算符重载 复杂 涉及到规则  重载 >>
    /*friend ostream & operator >> (ostream & _START, const Derry & derry1) {
        _START << " 多 哥开始输出了 " << derry1.x << " ! " << derry1.y << " 哥结束了 " << endl;
        return _START;

        // RxJava 链式调用  .操作符.操作符.操作符 你每次都是放回this  一个思路
    }*/

    // istream 输入 系统的
    friend istream & operator >> (istream & _START, Derry & derry) {
        // 接收用户的输入,把输入的信息,给x

        // _START >> derry.x;
        // _START >> derry.y;

        // 可读性不好,简化了
        _START >> derry.x >> derry.y;

        return _START;
    }
};

int main() {
    Derry derry1(1000, 2000);
    Derry derry2(3000, 4000);

    // Derry result = derry1 + derry2;

    // Derry result = derry2 - derry1;

    Derry result(1, 2);
    result++;
    ++result;

    cout << result.getX() << " , " << result.getY() << endl;

    cout << endl; // 系统的换行

    // 自定义的,系统没有考虑 你要输出 derry1对象,怎么办? 我们需要自定义 <<
    cout << derry1; // 单个的

    // cout >> derry1 >> derry1 >> derry1 >> derry1; // 多个的

    cout << endl; // 系统的换行

    // cout 输出的 C++
    // cin 输入的 C++

    Derry res;
    cin >> res; // >> 是我们自己重载的哦
    cout << "你输入的是:" << res.getX() << endl;
    cout << "你输入的是:" << res.getY() << endl;

    return 0;
}

括号运算符

cpp 复制代码
// 3.括号运算符。   数组 系统源码把此括号[i]给重载,  系统重载后的样子 *(arr+i)

#include <iostream>
using namespace std;

// 写一个小容器,模拟容器
class ArrayClass {

private:
    // C++ 默认都是系统值  size 系统值 -13275
    int size = 0; // 大小  开发过程中,给size赋默认值,不然会出现,后患无穷的问题
    int * arrayValue; // 数组存放 int 类型的很多值

public:
    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() {
    // 能在栈区的,尽量在栈区
    // 1.代码量少
    // 2.避免麻烦
    // 3.怕有问题
    // 4.栈区的回收,不是你负责的,责任推卸

    ArrayClass arrayClass;  // 栈区    实例出来的对象,是在堆区了

    arrayClass.set(0, 1000);
    arrayClass.set(1, 2000);
    arrayClass.set(2, 3000);
    arrayClass.set(3, 4000);
    arrayClass.set(4, 5000);

    printfArryClass(arrayClass);

    return 0;
}

C++对象继承

cpp 复制代码
// 4.C++对象继承。

#include <iostream>

using namespace std;

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;
    }
};

// 1.默认是 隐式代码: : private Person
// 2.私有继承:在子类里面是可以访问父类的成员,但是在类的外面不行
// 3.必须公开继承,才可以访问父类的成员
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();
    }
};

int main() {
    Student stu("李元霸", 99, "C++");

    // 公开继承,才可以拿父类的成员
    stu.name = "李四";

    return 0;
}

C++是有多继承的

cpp 复制代码
// C++是有多继承的
// Java语言不允许多继承,多继承有歧义,如果Java语言多继承 就会导致代码不健壮,(二义性)
// Java多实现:做的非常棒,严格避免出现 二义性问题(歧义)

#include <iostream>

using namespace std;

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 BaseActivity3 {
public:
    void onCreate() {
        cout << "BaseActivity3 onCreate" << endl;
    }

    void onStart() {
        cout << "BaseActivity3 onStart" << endl;
    }

    void show() {
        cout << "BaseActivity3 show" << endl;
    }
};

// 子类 继承 三个父类
class MainActivity1 : public BaseActivity1, public BaseActivity2, public BaseActivity3 {
public:
    void onCreate() {
        cout << "MainActivity1 onCreate" << endl;
    }

    void onStart() {
        cout << "MainActivity1 onStart" << endl;
    }

    void showSonInfo() {
        cout << "MainActivity1 showSonInfo" << endl;
    }

    // 解决方案二: 子类上 重写父类的show函数
    void show() {
        cout << "MainActivity1 show" << endl;
    }

};

int main() {
    // 这个是优先寻找子类的函数,因为特别明确,没有问题,还没有产生歧义(二义性)
    MainActivity1 mainActivity1; // 子类
    mainActivity1.onCreate();
    mainActivity1.onStart();
    mainActivity1.showSonInfo();

    // error: request for member 'show' is ambiguous
    // 不明确,二义性,歧义
    // mainActivity1.show();

    // 解决方案一: 明确指定父类 ::
    mainActivity1.BaseActivity3::show();
    mainActivity1.BaseActivity2::show();
    mainActivity1.BaseActivity1::show();

    // 解决方案二: 子类上 重写父类的show函数
    mainActivity1.show();

    return 0;
}

引发二义性问题

cpp 复制代码
// 多继承 二义性2:
// 在真实开发过程中,严格避免出现 二义性

#include <iostream>

using namespace std;

// 祖父类
class Object {
public:
    int number;
};

// 父类1
class BaseActivity1 : public Object {

};

// 父类2
class BaseActivity2 : public Object {

};

// 子类
class Son : public BaseActivity1, public BaseActivity2 {

    // 第二种解决方案: 在类中定义同名成员,覆盖掉父类的相关成员
public:
    int number;

};


int main() {
    Son son;

    // error: request for member 'show' is ambiguous  二义性 歧义
    // son.number = 2000;

    // 第一种解决方案: :: 明确指定
    son.BaseActivity1::number  = 1000;
    son.BaseActivity2::number  = 1000;

    // 第二种解决方案: 在类中定义同名成员,覆盖掉父类的相关成员
    son.number = 3000;

    // 第三种解决方案: 【虚基类】 属于 虚继承的范畴

    return 0;
}
cpp 复制代码
// 第三种解决方案: 【虚基类】 属于 虚继承的范畴
// 真实C++开始,是很少出现,二义性(歧义) 如果出现, 系统源码(系统用 第三种解决方案)

#include <iostream>

using namespace std;

// 祖父类
class Object{
public:
    int number;
    void show() {
        cout << "Object show run..." << endl;
    }
};

// 等下讲 virtual 的原理是什么 ...

// 父类1
class BaseActivity1 : virtual public Object {
// public:int number; // 人为制作二义性  error: request for member 'number' is ambiguous
};

// 父类2
class BaseActivity2 : virtual public Object {
// public:int number;
};

// 子类
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;

    return 0;
}
相关推荐
一只鹿鹿鹿4 小时前
智慧水利一体化建设方案
大数据·运维·开发语言·数据库·物联网
没有医保李先生5 小时前
字节对齐的总结
java·开发语言
蚊子码农6 小时前
算法题解记录--239滑动窗口最大值
数据结构·算法
liliangcsdn6 小时前
A3C算法从目标函数到梯度策略的探索
算法
Elastic 中国社区官方博客6 小时前
使用 Elastic 进行网络监控:统一网络可观测性
大数据·开发语言·网络·人工智能·elasticsearch·搜索引擎·全文检索
Codefengfeng6 小时前
Python Base环境中加包的方法
开发语言·python
清水白石0086 小时前
《Python 编程全景解析:从核心精要到测试替身(Test Doubles)五大武器的实战淬炼》
开发语言·python
陈天伟教授6 小时前
人工智能应用- 材料微观:06.GAN 三维重构
人工智能·神经网络·算法·机器学习·重构·推荐算法
liliangcsdn7 小时前
A3C强化学习算法的探索和学习
算法