C++ 面向对象、多继承

// Student.h

class Student {
private: // 私有的,外界不能访问
    char *name;
    int age;

public:
    void setAge(int age);
    void setName(char* name);
    int getAge();
    char* getName();

    // 空参构造函数
    Student(){
    }

    // 一参构造函数
    Student(char* name) : Student(name,80) {
        // 调用两参的构造函数,与 java 有点不同,又与 Kotlin 继承调用父类构造有点像
    }

    // 两参构造函数
    Student(char* name, int age) {
    }

    // 析构函数 对象的临终遗言,一般用来做释放工作,与 java 的 finalize() 类似
    ~Student() {
    }

    // 拷贝构造函数,它默认有,可以重写
    // 对象1 = 对象2
    Kang(const Kang &kang) { // 常量引用:只读
        // 可以对原来的对象做一些操作
    }

    // const修饰方法后面:只读的函数
    void showInfo() const {
    }

    // 定义友元函数,供外界重写来访问私有成员
    friend void updateAge(Kang *kang,int age);

    // 友元类,友元类可访问自身的私有成员
    friend class Person;
    // java 中能用反射获取到其他类私有成员,底层就是友元实现的


    // 运算符重载,基本上都是写在类里面的,因为可以拿到类的私有成员
    // const:不允许修改,只读
    // &:性能的提高,如果没有 & 运行 + 会构建新的副本
    Student operator+(const Student &s1) {
        int number = this->getAge() + s1.age;
        return Student(this->getName(), number);
    }
};

 与 java 一样,C++也是面向对象的,和 java 非常相似:
新创建一个头文件 Student.h,里面定义了一个 Student 类

构造函数:和 java 相比大部分相同,只是在构造函数之间的相互调用有一些出入
析构函数:在对象销毁时会调用此函数,类似 java 的 finalize()
拷贝构造函数:在对象之间直接赋值会调用此函数,可以在赋值时做一些操作

友元函数 / 类:都基于友元思想,只能在类中定义,友元函数供外界重写来访问私有成员,友元类能直接访问私有成员

运算符重载:就是自定义符号运算规则,基本上都是写在类里面,因为可以拿到类的私有成员


// Student.cpp

#include "Student.h"

void Student::setAge(int age) {
    this->age = age;
}

void Student::setName(char *name) {
    this->name = name;
}

int Student::getAge() {
    return this->age;
}

char *Student::getName() {
    return this->name;
}

为了演示,我只在实现文件实现 get/set,其实把全部函数的实现都写在头文件都可以的,但是为了解耦和可读性,最好还是在头文件声明实现文件中进行实现


#include <iostream> // C++ 的标准支持
#include "Student.h"

// new/delete 是一套 会调用构造函数 与 析构函数 【C++标准规范】
// malloc/ free 是一套 不调用构造函数 与 析构函数 【C的范畴,虽然不推荐,但是也是可以的】

int main() {

    Student s1; // 调用空参构造函数(栈区开辟)
    Student s2("小民"); // 调用一个参数的构造函数(栈区开辟)

    // new 关键字返回的是对象的指针
    Student *s3 = new Student("小红"); // 调用一个参数的构造函数(堆区开辟)
    delete s3;

    // 调用拷贝构造函数
    Student s4 = s1;

    return 0;
}

与 java 不同,像 Student s1,java 只是定义了一个空的变量,而 C++ 是实打实的创建了一个对象

new 的时候,C++返回的是一个指针,销毁时需要手动调用 delete 做释放工作。


总所周知 java 是单继承的,但是在 C++ 中是多继承的,但是多继承可能会带来一些冲突(二义性)

// Test.cpp

#include <iostream>

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

// 父类1
class Parent1 : public Object {
};

// 父类2
class Parent2 : public Object {
};

// 子类
class Son : public Parent1, public Parent2 {
};

int main() {
    Son son;
    // 报错,编译器不知道找哪个父类的 number
    son.number = 2000;

    // 方法一:明确指定
    son.Parent1::number = 1000;

    // 方法二:Parent1 和 Parent2 都使用虚继承,例如:
    // class Parent1 : virtual public Object {
    // 这样子 子类去访问父类成员时,直接访问祖父类,就不会有歧义了

    return 0;
}

代码中创建一个祖父类 Object,Parent1 和 Parent2 分别继承了 Object,子类双继承(Parent1 和 Parent2)如图:

 在 main 函数中可以看到,直接在 son 中访问父类成员 number 是编译不通过的,因为编译器不知道找哪个父类的 number,这个问题需要解决,解决办法:

方法一:明确指定是哪个父类即可

方法二:父类使用虚继承,Parent1 和 Parent2 都使用 virtual 关键字继承 Object,这样子在子类去访问父类成员时,会直接访问祖父类,这样就不会有歧义了 

方法三:比较 low,子类覆盖定义父类变量,比较简单,就不演示了


在真实的开发过程中,应当严格避免二义性。

这样子看来,java 就显得非常好,单继承 + 多实现不会出现二义性,但是如果需要底层开发和对性能有要求的话,C++仍是不二之选

猜你喜欢

转载自blog.csdn.net/weixin_47592544/article/details/130155073