C++ day5 练习
一、练习1
编写一个长方形类;
私有成员: a, b
构造函数初始化;
set、get 接口;
编写一个正方形类,继承自长方形类;
构造函数初始化;
无论如何,正方形类对象总是正方形的;
【代码】:
#include <iostream>
using namespace std;
class ABAB{
private:
int a;
int b;
public:
ABAB(int a=0, int b=0):a(a), b(b){}
void setA(int l){a = l;}
void setB(int l){b = l;}
int getA(){return a;}
int getB(){return b;}
};
class AABB:public ABAB{
public:
AABB(int a=0, int b=0)
:ABAB(a, b)
{}
void setA(int a){
ABAB::setA(a);
ABAB::setB(a);
}
void setB(int b){
ABAB::setA(b);
ABAB::setB(b);
}
};
int main()
{
AABB aabb;
aabb.setA(5);
aabb.setB(5);
cout << "a=" << aabb.getA() << endl;
cout << "b=" << aabb.getB() << endl;
return 0;
}
二、练习2
写一个三角形类,拥有私有成员;
a,b,c 三条边
写好构造函数初始化 abc 以及 abc 的set、get 接口;
再写一个等腰三角形类,继承自三角形类:
1、写好构造函数,初始化三条边;
2、要求无论如何,等腰三角形类对象,总是等腰的;
再写一个等边三角形类,继承自等腰三角形类;
1、写好构造函数,初始化三条边;
2、要求无论如何,等腰三角形类对象,总是等边;
【代码】:
#include <iostream>
using namespace std:
class ABC{
private:
int a;
int b;
int c;
public:
ABC(int a=0; int b=0; int c=0):a(a), b(b), c(c){}
void setA(int l){a = l;}
void setB(int l){b = l;}
void setC(int l){c = l;}
int getA(){return a;}
int getB(){return b;}
int getC(){return c;}
};
class AAC:public ABC{
public:
AAB(int ab=0; int c=0)
:ABC(ab, ab, c)
{}
void setA(int a){
ABC::setA(a);
ABC::setB(a);
}
void setB(int b){
ABC::setA(b);
ABC::setB(b);
}
};
class AAA:public AAC{
public:
AAA(int ab=0, int ac=0, int bc=0)
:AAC(ab, ac, bc)
{}
void setA(int a){
AAC::setA(a);
AAC::setB(a);
AAC::setC(a);
}
void setB(int b){
AAC::setA(b);
AAC::setB(b);
AAC::setC(b);
}
void setC(int c){
AAC::setA(c);
AAC::setB(c);
AAC::setC(c);
}
};
int main()
{
AAA aaa;
aaa.setA(5);
aaa.setB(5);
aaa.setC(5);
cout << "a=" << aaa.getA() << endl;
cout << "b=" << aaa.getB() << endl;
cout << "c=" << aaa.getC() << endl;
return 0;
}
三、练习3
封装消息队列
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 中;
编写程序测试。
【代码】:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
using namespace std;
class Msg {
private:
key_t key;
int id;
int channel;
// 消息结构体
struct msgbuf {
long channel; // 消息类型(频道)
char text[512]; // 消息内容
};
public:
// 构造函数
Msg(const string& filename = "") {
key = ftok(filename.data(), 1); // 生成 key
id = msgget(key, IPC_CREAT | 0666); // 创建消息队列
if (id == -1) {
perror("msgget");
exit(EXIT_FAILURE);
}
}
// 析构函数
~Msg() {
msgctl(id, IPC_RMID, 0); // 删除消息队列
}
// 重载 << 运算符,用于发送消息
Msg& operator<<(const string& str) {
msgbuf buf = {0};
strncpy(buf.text, str.data(), sizeof(buf.text) - 1); // 复制消息内容
buf.channel = channel; // 设置消息频道
if (msgsnd(id, &buf, strlen(buf.text) + 1, 0) == -1) { // 发送消息
perror("msgsnd");
}
return *this;
}
// 重载 >> 运算符,用于接收消息
Msg& operator>>(string& str) {
msgbuf buf = {0};
if (msgrcv(id, &buf, sizeof(buf.text), channel, 0) == -1) { // 接收消息
perror("msgrcv");
}
str = buf.text; // 将消息内容存入 str
return *this;
}
// 重载 [] 运算符,用于设置频道
Msg& operator[](int channel) {
this->channel = channel; // 设置当前频道
return *this;
}
};
int main() {
Msg m; // 创建消息队列对象
// 向 1 号频道发送消息
m[1] << "helloworld";
// 从 1 号频道接收消息
string str;
m[1] >> str;
cout << "Received message: " << str << endl;
return 0;
}
四、练习4
封装信号灯集
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].operator+(1) s[1] - 1; // 让信号灯集中的第1个信号量的值 -1;
追加 operator ++ 功能,即解锁一次;
以及 operator-- 功能, 即上锁一次;
【代码】:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sstream>
#include <vector>
#include <memory>
#include <sys/ipc.h>
#include <sys/sem.h>
using namespace std;
class Sem {
private:
key_t key;
int id;
int index;
public:
Sem(const string& filename = "", int n, int val) {
key = ftok(filename.data(), 'R');
id = semget(key, n, IPC_CREAT | 0666);
for (int i = 0; i < n; i++) {
semctl(id, i, SETVAL, val);
}
}
~Sem() {
semctl(id, 0, IPC_RMID);
}
Sem& operator++() { // 前置++
sembuf buf = {};
buf.sem_num = index;
buf.sem_op = 1;
buf.sem_flg = SEM_UNDO;
semop(id, &buf, 1);
return *this;
}
Sem& operator--() { // 前置--
sembuf buf = {};
buf.sem_num = index;
buf.sem_op = -1;
buf.sem_flg = SEM_UNDO;
semop(id, &buf, 1);
return *this;
}
friend Sem& operator+(const Sem& l, int val);
friend Sem& operator-(const Sem& l, int val);
friend Sem& operator[](const Sem& l, int index);
};
Sem& operator+(const Sem& l, int val) {
sembuf buf = {};
buf.sem_num = l.index;
buf.sem_op = abs(val);
buf.sem_flg = SEM_UNDO;
semop(l.id, &buf, 1);
return const_cast<Sem&>(l);
}
Sem& operator-(const Sem& l, int val) {
sembuf buf = {};
buf.sem_num = l.index;
buf.sem_op = -abs(val);
buf.sem_flg = SEM_UNDO;
semop(l.id, &buf, 1);
return const_cast<Sem&>(l);
}
Sem& operator[](const Sem& l, int index) {
const_cast<Sem&>(l).index = index;
return const_cast<Sem&>(l);
}
int main(int argc, const char** argv) {
Sem sem("semfile", 1, 1); // 创建一个信号量,初始值为1
// 测试 operator++
cout << "Unlocking semaphore..." << endl;
++sem;
cout << "Semaphore unlocked." << endl;
// 测试 operator--
cout << "Locking semaphore..." << endl;
--sem;
cout << "Semaphore locked." << endl;
return 0;
}