C++学习三

一、运算符重载

#include 
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) {}

    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);
    }*/

    // 系统是这样写的  常量引用:不允许修改,只读模式
    // & 性能的提高,如果没有&  运行+ 构建新的副本,会浪费性能
    // 如果增加了& 引用是给这块内存空间取一个别名而已
    Derry operator + (const Derry& derry1) {
        //int x = this->x + derry1.getX(); //这样是不行的,虽然是get函数,但是系统怕你在函数里面有修改值
        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;
    }
};
// 在真实开发过程中,基本上都是写在类的里面的,因为外部是不能获取内部的私有成员的
// 把+重载 运算符重载
//类外运算符重载
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() {
    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;
}

二、继承

1、基本
#include 

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;
}
2、多继承、二义性
#include 
using namespace std;
class BaseActivity1 {
public:
    void onCreate() {
        cout << "BaseActivity1 onCreate" << endl;
    }
    void show() {
        cout << "BaseActivity1 show" << endl;
    }
};

class BaseActivity2 {
public:
    void onCreate() {
        cout << "BaseActivity2 onCreate" << endl;
    }
    void show() {
        cout << "BaseActivity2 show" << endl;
    }
};

class BaseActivity3 {
public:
    void onCreate() {
        cout << "BaseActivity3 onCreate" << endl;
    }
    void show() {
        cout << "BaseActivity3 show" << endl;
    }
};

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

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

};

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

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

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

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

    return 0;
}
3、属性二义性
#include 
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;
    //  二义性 歧义
    // son.number = 2000;

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

    // 第二种解决方案: 在类中定义同名成员,覆盖掉父类的相关成员
    son.number = 3000;
    // 第三种解决方案: 【虚基类】 属于 虚继承的范畴
    return 0;
}
4、虚基类(虚继承)
#include 
using namespace std;
// 祖父类
class Object{
public:
    int number;
    void show() {
        cout << "Object show run..." << endl;
    }
};
// 父类1
class BaseActivity1 : virtual public Object {
// public:int number; // 人为制作二义性  
};
// 父类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();
    return 0;
}
二义性.png

三、多态(虚函数)

// 多态(虚函数)。   动态多态(程序的角度上:程序在运行期间才能确定调用哪个类的函数 == 动态多态的范畴)
// Java语言默认支持多态
// C++默认关闭多态,怎么开启多态? 虚函数  在父类上给函数增加 virtual关键字
// 请问什么是多态? 父类的引用指向之类的对象,同一个方法有不同的实现,重写(动态多态)和   重载(静态多态)
#include 
using namespace std;
class BaseActivity {
public:
     virtual void onStart() { //虚函数
        cout << "BaseActivity onStart" << endl;
    }
};

class HomeActivity : public BaseActivity {
public:
    void onStart() { // 重写父类的函数
        cout << "HomeActivity onStart" << endl;
    }
};

class LoginActivity : public BaseActivity {
public:
    void onStart() { // 重写父类的函数
        cout << "LoginActivity onStart" << endl;
    }
};

void startToActivity(BaseActivity * baseActivity) {
    baseActivity->onStart();
}

int main() {
    // TODO 第一版本 如果不是虚函数打印的都是BaseActivity
    HomeActivity *homeActivity = new HomeActivity();
    LoginActivity *loginActivity = new LoginActivity();

    startToActivity(homeActivity);
    startToActivity(loginActivity);

    if (homeActivity && loginActivity) delete homeActivity; delete loginActivity;

    cout << endl;

    // TODO 第二个版本
    BaseActivity * activity1 = new HomeActivity();
    BaseActivity * activity2 = new LoginActivity();
    startToActivity(activity1);
    startToActivity(activity2);
    return 0;
}

// 静态多态 (编译期已经决定,调用哪个函数了,这个就属于静态多态的范畴)  重载(静态多态)
#include 
using namespace std;
void add(int number1, int number2) {
    cout << number1 + number2 << endl;
}
void add(float number1, float number2) {
    cout << number1 + number2 << endl;
}
void add(double number1, double number2) {
    cout << number1 + number2 << endl;
}
int main() {
    add(10000, 10000);
    add(1.9f, 2.8f);
    add(545.4, 654.54);
    return 0;
}

四、纯虚函数

// 纯虚函数(Java版抽象类)
// C++纯虚函数(C++没有抽象类)  相当于 Java的抽象类  为了更好理解

#include 
using namespace std;

// 抽象类/纯虚函数: 分为:1.普通函数, 2.抽象函数/纯虚函数
class BaseActivity {
private:
    void setContentView(string layoutResID) {
        cout << "XmlResourceParser解析布局文件信息... 反射" << endl;
    }

public:
    // 1.普通函数
    void onCreate() {
        setContentView(getLayoutID());
        initView();
        initData();
        initListener();
    }

    // 纯虚函数是必须继承的(如果子类没有重写纯虚函数,子类就是抽象类), 虚函数是不是不必须的

    // 2.抽象函数/纯虚函数
    // virtual string getLayoutID(); // 虚函数
    virtual string getLayoutID() = 0; // 纯虚函数
    virtual void initView() = 0;
    virtual void initData() = 0;
    virtual void initListener() = 0;
};

// 子类 MainActivity
class MainActivity : public BaseActivity { // MainActivity如果没有重新父类的纯虚函数,自己就相当于 抽象类了
    string getLayoutID() {
        return "R.layout.activity_main";
    }

    void initView()  {
    }

    void initData() {
    }

    void initListener() { 
    }
};

五、全纯虚函数

// 虚函数  纯虚函数 全纯虚函数(C++没有接口) 等价于  全纯虚函数(Java版接口)。
#include 
using namespace std;
class Student {
    int _id;
    string name;
    int age;
};

// 此类所有的函数 ,都是纯虚函数,就相当于 Java的接口了
class ISudent_DB {
    virtual void insertStudent(Student student) = 0;
    virtual void deleteStudent(int _id) = 0;
    virtual void updateStudent(int _id, Student student) = 0;
    virtual Student queryByStudent(Student student) = 0;
};

// Java的实现类
class Student_DBImpl1 : public ISudent_DB {
public:
    void insertStudent(Student student) {
        // 插入操作,省略代码...
    }

    void deleteStudent(int _id) {
        // 删除操作,省略代码...
    }

    void updateStudent(int _id, Student student) {
        // 更新操作,省略代码...
    }

    Student queryByStudent(Student student) {
        // 查询操作,省略代码...
    }
};
int main() {
    Student_DBImpl1 studentDbImpl1;
    Student_DBImpl2 studentDbImpl2;
    Student_DBImpl3 studentDbImpl3;

    cout << "Success" << endl;

    return 0;
}
登录实例:
// 回调  Java的登录 简单的 接口
#include 
using namespace std;
// 登录成功的Bean
class SuccessBean {
public:
    string username;
    string userpwd;

    SuccessBean(string username, string userpwd)
    :username(username), userpwd(userpwd) {}
};

// 登录响应的接口  成功,错误
class ILoginResponse {
public:
    // 登录成功
    virtual void loginSuccess(int code, string message, SuccessBean successBean) = 0;

    // 登录失败
    virtual void loginError(int code, string message) = 0;
};

// 登录的API动作
void loginAction(string name, string pwd, ILoginResponse & loginResponse) {
    if (name.empty() || pwd.empty()) {
        cout << "用户名或密码为空!" << endl;
        return;
    }

    if ("Derry" == name && "123" == pwd) {
        loginResponse.loginSuccess(200, "登录成功", SuccessBean(name, "恭喜你进入"));
    } else {
        loginResponse.loginError(404, "登录错误,用户名或密码错误...");
    }
}

// 写一个实现类,继承接口
// 接口实现类
class ILoginResponseImpl : public ILoginResponse {
public:
    // 登录成功
    void loginSuccess(int code, string message, SuccessBean successBean) {
        cout << "恭喜登录成功 " << "code:" << code << " message:" << message
        << "successBean:" << successBean.username << "," << successBean.userpwd << endl;
    }

    // 登录失败
    void loginError(int code, string message) {
        cout << " 登录失败 " << "code:" << code << " message:" << message << endl;
    }
};

int main() {

    // 做实验
    // Allocating an object of abstract class type 'ILoginResponse'
    // 正在分配抽象类型为ILoginResponse的对象  不能被实例化
    // 纠结:为什么不可以
    // 1.他不是Java的接口,C++也没有接口,他只是像接口而已。
    // 2.他也不是抽象类,C++也没有抽象类,他只是像抽象类而已。
    // 3.他是纯虚函数的类,此类决定不准你实例化  无论堆区 还是栈区
    /*new ILoginResponse() {
        // 登录成功
        void loginSuccess(int code, string message, SuccessBean successBean) {

        }

        // 登录失败
        void loginError(int code, string message) {

        }
    }*/

    string username;
    cout << "请输入用户名.." << endl;
    cin >> username;

    string userpwd;
    cout << "请输入密码.." << endl;
    cin >> userpwd;

    ILoginResponseImpl iLoginResponse;
    loginAction(username, userpwd, iLoginResponse);

    return 0;
}

六、模板函数

// 模版函数(Java版泛型)。  C++没有泛型 C++的模板函数 非常类似于 Java的泛型
#include 
using namespace std;
// 加分合集  int double float ... 你都要考虑,你是不是要定义很多的 函数
/*void addAction(int n1, int n2) {
    cout << "addAction(int n1, int n2):" << n1 + n1 << endl;
}
void addAction(float n1, float n2) {
    cout << "addAction(int n1, int n2):" << n1 + n1 << endl;
}
void addAction(double n1, double n2) {
    cout << "addAction(int n1, int n2):" << n1 + n1 << endl;
}*/
// 模板函数  == Java的泛型解决此问题
template 
void addAction(TT n1, TT n2) {
    cout << "模板函数:" << n1 + n2 << endl;
}
int main() {
    addAction(1, 2);
    addAction(10.2f, 20.3f);
    addAction(545.34, 324.3);
    addAction("AAA", "BBB");
    return 0;
}

你可能感兴趣的:(C++学习三)