继承 ——类的功能拓展

继承允许一个类(派生类)基于另一个类(基类)创建,
派生类复用基类的属性和方法,扩展或修改基类的行为。
。。。。。。

派生类访问基类的私有成员

基类的私有成员,写set get 公开接口的话

派生类就继承这些公开接口,自然,派生类就能通过公开接口访问基类的私有成员

派生类的构造函数,初始化基类的成员属性

想要初始化,只能通过派生类的 构造函数的 列表初始化部分

但派生类构造函数的初始化列表部分,根本访问不放基类的成员属性(无论公开还是私有)

调用派生类构造函数的时候,会自动的调用基类构造函数

基类和派生类出现同名函数(同名属性)

class Base{
    void show(){
        cout << "基类的show" << endl;
    }
};
class Derived:public Base{
    void show(int a){
        cout << "派生类的show" << endl;
    }

};
int main(int argc,const char** argv){
    Derived d;
    d.show();
}

这段代码编译报错:
原因:基类的show和派生类的show没有形成重载函数(作用域相同)
函数调用不会根据具体的实参,调用不同版本的函数
 d.show() 调用的是派生类的show函数

调用基类的show:
d.Base::show()

单继承

只继承一个基类。

// 基类
class Animal {
public:
    void eat() {
        cout << "动物在吃东西" << endl;
    }
};

// 派生类
class Dog : public Animal {
public:
    void bark() {
        cout << "汪汪汪" << endl;
    }
};

int main() {
    Dog dog;
    dog.eat();  // 调用基类的方法
    dog.bark(); // 调用派生类的方法
    return 0;
}

多继承

继承多个基类。

// 基类 1
class Animal {
public:
    void eat() {
        cout << "动物在吃东西" << endl;
    }
};
// 基类 2
class Mammal {
public:
    void breathe() {
        cout << "哺乳动物在呼吸" << endl;
    }
};
​​​​​​​// 派生类
class Dog : public Animal, public Mammal {
public:
    void bark() {
        cout << "汪汪汪" << endl;
    }
};

int main() {
    Dog dog;
    dog.eat();     // 调用 Animal 的方法
    dog.breathe(); // 调用 Mammal 的方法
    dog.bark();    // 调用 Dog 的方法
    return 0;
}

多层继承

派生类作为另派生类的基类。

// 基类
class Animal {
public:
    void eat() {
        cout << "动物在吃东西" << endl;
    }
};
// 派生类 1
class Mammal : public Animal {
public:
    void breathe() {
        cout << "哺乳动物在呼吸" << endl;
    }
};
// 派生类 2
class Dog : public Mammal {
public:
    void bark() {
        cout << "汪汪汪" << endl;
    }
};

int main() {
    Dog dog;
    dog.eat();     // 调用 Animal 的方法
    dog.breathe(); // 调用 Mammal 的方法
    dog.bark();    // 调用 Dog 的方法
    return 0;
}

函数重写(Override)

派生类可以重写基类的虚函数,实现多态性。

优点

1. **代码复用**:派生类可以复用基类的代码,减少重复代码。
2. **可扩展性**:可以通过继承扩展基类的功能。
3. **灵活性**:通过多态性,可以实现运行时动态绑定。

练习

编写一个长方形类,
私有成员 a,b
构造函数初始化
set get 接口
编写一个正方形类,继承自长方形类
    构造函数初始化
    无论如何,正方形类对象总是正方形的
// 长方形类
class Rectangle {
private:
    int a; // 长
    int b; // 宽

public:
    Rectangle(int a = 0, int b = 0) : a(a), b(b) {
        cout << "Rectangle created: a = " << a << ", b = " << b << endl;
    }
    void setA(int a) {
        this->a = a;
    }
    void setB(int b) {
        this->b = b;
    }
    int getA() const {
        return a;
    }
    int getB() const {
        return b;
    }
    int area() const {
        return a * b;
    }
};
// 正方形类
class Square : public Rectangle {
public:
    Square(int side = 0) : Rectangle(side, side) {
        cout << "Square created: side = " << side << endl;
    }
    // 重写 setA,确保长和宽相等
    void setA(int a) {
        Rectangle::setA(a);
        Rectangle::setB(a);
    }
    void setB(int b) {
        Rectangle::setA(b);
        Rectangle::setB(b);
    }
};
int main() {
    // 测试长方形类
    Rectangle rect(3, 4);
    cout << "Rectangle area: " << rect.area() << endl;
    rect.setA(5);
    rect.setB(6);
    cout << "Modified Rectangle area: " << rect.area() << endl;

    // 测试正方形类
    Square square(5);
    cout << "Square area: " << square.area() << endl;
    square.setA(7);
    cout << "Modified Square area: " << square.area() << endl;
    cout << "Square sides: a = " << square.getA() << ", b = " << square.getB() << endl;

    return 0;
}
封装消息队列
class Msg{
    key_t key
    int id;
    int channel
}
实现以下功能
Msg m("文件名")
m[1].send("数据"),将数据发送到1号频道中
string str = m[1].recv(int size) 从1号频道中读取消息,并且返回
把 send 改成 operator<< ,recv 改成 operator>>
实现效果:
    m[1] << "helloworld" 将 "helloworld" 写入消息队列的1号频道中
    m[1] >> str 读取消息队列中1频道中的消息,存入 str 
class Msg {
public:
    struct message {//删除消息队列
        long mtype; // 类型(频道)
        char mtext[1024]; // 数据
    };

    Msg(const string& filename) {// 创建或打开消息队列
        key = ftok(filename.c_str(), 'M'); // 使用文件名生成 key        
        id = msgget(key, 0666 | IPC_CREAT); // 创建或打开消息队列        
    }
    ~Msg() {//删除消息队列
        msgctl(id, IPC_RMID, nullptr);
    }
    
    class Channel {//一个频道
    public:
        Channel(int msgid, int channel) : msgid(msgid), channel(channel) {}

        // 重载 << :发送消息
        void operator<<(const string& data) {
            message msg;
            msg.mtype = channel; // 设置频道
            strncpy(msg.mtext, data.c_str(), sizeof(msg.mtext)); // 拷贝数据
            msgsnd(msgid, &msg, sizeof(msg.mtext), 0);
        }

        // 重载 >> :接收消息
        void operator>>(string& data) {
            message msg;
            msgrcv(msgid, &msg, sizeof(msg.mtext), channel, 0) ;
            data = string(msg.mtext); // 将消息数据存入字符串
        }

    private:
        int msgid;
        int channel;
    };

    // 重载 [] :返回指定频道的 Channel 对象
    Channel operator[](int channel) {
        return Channel(id, channel);
    }

private:
    key_t key;
    int id;
};

int main() {        
        Msg m("msgfile");// 创建消息队列

        // 发送消息到 1 号频道
        m[1] << "Hello, Channel 1!";

        // 从 1 号频道接收消息
        string str;
        m[1] >> str;
        cout << "Received from Channel 1: " << str << endl;

        // 发送消息到 2 号频道
        m[2] << "Hello, Channel 2!";

        // 从 2 号频道接收消息
        m[2] >> str;
        cout << "Received from Channel 2: " << str << endl;
        return 0;
}
封装信号灯集
class Sem{
    key_t key
    int id;   
    int index
}
实现以下功能
Sem s(参数x,参数y):创建信号灯集,信号灯集中存在 x 个信号量,初始化为 y
s[1].init(10):手动初始化信号灯集中的第1个信号量,初始化成 10
s[1] + 1 让信号灯集中的第1个信号量的值 +1
s[1] - 1 让信号灯集中的第1个信号量的值 -1
追加 operator ++ 功能,即解锁一次
以及 operator-- 功能, 即上锁一次
class Sem {
public:
    // 构造函数:创建信号灯集,并初始化所有信号量为 y
    Sem(int x, int y) : count(x) {
        key = ftok(".", 'S'); // 使用当前目录和字符 'S' 生成 key       
        id = semget(key, x, 0666 | IPC_CREAT); // 创建信号灯集        
        // 初始化所有信号量为 y
        union semun {
            int val;
            struct semid_ds *buf;
            unsigned short *array;
        } arg;
        arg.val = y;
        for (int i = 0; i < x; i++) 
            semctl(id, i, SETVAL, arg);
    }

    // 析构函数:删除信号灯集
    ~Sem() {
        semctl(id, 0, IPC_RMID);
    }

    // 内部类:表示一个信号量
    class Semaphore {
    public:
        Semaphore(int semid, int index) : semid(semid), index(index) {}

        // 手动初始化信号量
        void init(int value) {
            union semun {
                int val;
                struct semid_ds *buf;
                unsigned short *array;
            } arg;
            arg.val = value;
            semctl(semid, index, SETVAL, arg);
        }

        // 重载 + :信号量值加 1
        void operator+(int value) {
            struct sembuf op;
            op.sem_num = index;
            op.sem_op = value; // 增加的值
            op.sem_flg = 0;
            semop(semid, &op, 1) ;
        }

        // 重载 - :信号量值减 1
        void operator-(int value) {
            struct sembuf op;
            op.sem_num = index;
            op.sem_op = -value; // 减少的值
            op.sem_flg = 0;
            semop(semid, &op, 1) ;
        }

        // 重载 ++ :解锁一次(信号量加 1)
        void operator++() {
            (*this) + 1;
        }

        // 重载 -- :上锁一次(信号量减 1)
        void operator--() {
            (*this) - 1;
        }

        // 获取信号量的当前值
        int getValue() {
            return semctl(semid, index, GETVAL);
        }

    private:
        int semid;
        int index;
    };

    // 重载 [] :返回指定索引的信号量
    Semaphore operator[](int index) {
        return Semaphore(id, index);
    }

private:
    key_t key;
    int id;
    int count; // 信号量数量
};

// 测试程序
int main() {
        // 创建信号灯集,包含 3 个信号量,初始化为 5
        Sem s(3, 5);

        // 手动初始化第 1 个信号量为 10
        s[1].init(10);
        cout << "Semaphore 1 value after init: " << s[1].getValue() << endl;

        // 第 1 个信号量加 1
        s[1] + 1;
        cout << "Semaphore 1 value after +1: " << s[1].getValue() << endl;

        // 第 1 个信号量减 1
        s[1] - 1;
        cout << "Semaphore 1 value after -1: " << s[1].getValue() << endl;

        // 解锁一次(信号量加 1)
        ++s[1];
        cout << "Semaphore 1 value after ++: " << s[1].getValue() << endl;

        // 上锁一次(信号量减 1)
        --s[1];
        cout << "Semaphore 1 value after --: " << s[1].getValue() << endl;
       return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值