C++实践参考——动物这样叫

返回:贺老师课程教学链接  项目要求


【项目-动物这样叫】

下面是给出的基类Animal声明和main()函数。

class Animal
{
public:
  virtual void cry()
    {
      cout<<"不知哪种动物,让我如何学叫?"<<endl;
    }
};
int main( ){
    Animal *p;
    p = new Animal();
    p->cry(); 
    Mouse m1("Jerry",'m'); 
    p=&m1;
    p->cry(); 
    Mouse m2("Jemmy",'f');
    p=&m2;
    p->cry(); 
    Cat c1("Tom");
    p=&c1;
    p->cry(); 
    Dog d1("Droopy");
    p=&d1;
    p->cry(); 
    Giraffe g1("Gill",'m');
    p=&g1;
    p->cry(); 
    return 0;
}
程序的运行结果将是:

1、根据给出的main()函数和运行结果的提示,设计出相关的各个类,注意观察运行结果,提取出每个类中需要的数据成员,并匹配上需要的成员函数。
2、显然,Animal设计为抽象类更合适,Animal不需要能够实例化,是专门作基类使用的。改造程序,使Animal设计为抽象类,这时main()函数中p = new Animal();将出错,将此行删除。
3、每一个Animal的派生类都有一个“名字”数据成员,这个成员设置为基类Animal的成员更好。改造上面的程序,将“名字”成员作为抽象类Animal数据成员被各派生类使用。

[参考解答]

1、根据给出的main()函数和运行结果的提示,设计出相关的各个类,注意观察运行结果,提取出每个类中需要的数据成员,并匹配上需要的成员函数。

#include "iostream"
#include<string>
using namespace std;
class Animal
{
public:
    virtual void cry()
    {
        cout<<"不知哪种动物,让我如何学叫?"<<endl;
    }
};

class Mouse : public Animal
{
private:
    string name;
    char sex;
public:
    Mouse(string nam, char s):name(nam),sex(s) {}
    virtual void cry()
    {
        cout<<"我叫"<<name<<",是一只"<<((sex=='m')?"男":"女")<<"老鼠,我的叫声是:吱吱吱!"<<endl;
    }
};

class Cat : public Animal
{
private:
    string name;
public:
    Cat(string nam):name(nam) {}
    virtual void cry()
    {
        cout<<"我叫"<<name<<",是一只猫,我的叫声是:喵喵喵!"<<endl;
    }
};

class Dog : public Animal
{
private:
    string name;
public:
    Dog(string nam):name(nam) {}
    virtual void cry()
    {
        cout<<"我叫"<<name<<",是一条狗,我的叫声是:汪汪汪!"<<endl;
    }
};

class Giraffe : public Animal
{
private:
    string name;
    char sex;
public:
    Giraffe(string nam,char s):name(nam), sex(s) {}
    virtual void cry()
    {
        cout<<"我叫"<<name<<",是"<<((sex=='m')?"男":"女")<<"长颈鹿,我的脖子太长,发不出声音来!"<<endl;
    }
};

int main( )
{
    Animal *p;
    p = new Animal();
    p->cry(); //输出: 不知哪种动物,让我如何学叫?
    Mouse m1("Jerry",'m');
    p=&m1;
    p->cry(); //输出: 我叫Jerry,是一只男老鼠,我的叫声是:吱吱吱!
    Mouse m2("Jemmy",'f');
    p=&m2;
    p->cry(); //输出: 我叫Jemmy,是一只女老鼠,我的叫声是:吱吱吱!
    Cat c1("Tom");
    p=&c1;
    p->cry(); //输出: 我叫Tom,是一只猫猫,我的叫声是:喵喵喵!
    Dog d1("Droopy");
    p=&d1;
    p->cry(); //输出: 我叫Droopy,是一条狗狗,我的叫声是:汪汪汪!
    Giraffe g1("Gill",'m');
    p=&g1;
    p->cry(); //输出: 我叫Gill,是男长颈鹿,脖子太长,发不出声音来!
    return 0;
}

2、显然,Animal设计为抽象类更合适,Animal不需要能够实例化,是专门作基类使用的。改造程序,使Animal设计为抽象类,这时main()函数中p = new Animal();将出错,将此行删除。

#include "iostream"
#include<string>
using namespace std;
class Animal
{
public:
    virtual void cry() = 0;
};

class Mouse : public Animal
{
private:
    string name;
    char sex;
public:
    Mouse(string nam, char s):name(nam),sex(s) {}
    virtual void cry()
    {
        cout<<"我叫"<<name<<",是一只"<<((sex=='m')?"男":"女")<<"老鼠,我的叫声是:吱吱吱!"<<endl;
    }
};

class Cat : public Animal
{
private:
    string name;
public:
    Cat(string nam):name(nam) {}
    virtual void cry()
    {
        cout<<"我叫"<<name<<",是一只猫,我的叫声是:喵喵喵!"<<endl;
    }
};

class Dog : public Animal
{
private:
    string name;
public:
    Dog(string nam):name(nam) {}
    virtual void cry()
    {
        cout<<"我叫"<<name<<",是一条狗,我的叫声是:汪汪汪!"<<endl;
    }
};

class Giraffe : public Animal
{
private:
    string name;
    char sex;
public:
    Giraffe(string nam,char s):name(nam), sex(s) {}
    virtual void cry()
    {
        cout<<"我叫"<<name<<",是"<<((sex=='m')?"男":"女")<<"长颈鹿,我的脖子太长,发不出声音来!"<<endl;
    }
};

int main( )
{
    Animal *p;
//    p = new Animal();
//    p->cry(); //输出: 不知哪种动物,让我如何学叫?
    Mouse m1("Jerry",'m');
    p=&m1;
    p->cry(); //输出: 我叫Jerry,是一只男老鼠,我的叫声是:吱吱吱!
    Mouse m2("Jemmy",'f');
    p=&m2;
    p->cry(); //输出: 我叫Jemmy,是一只女老鼠,我的叫声是:吱吱吱!
    Cat c1("Tom");
    p=&c1;
    p->cry(); //输出: 我叫Tom,是一只猫猫,我的叫声是:喵喵喵!
    Dog d1("Droopy");
    p=&d1;
    p->cry(); //输出: 我叫Droopy,是一条狗狗,我的叫声是:汪汪汪!
    Giraffe g1("Gill",'m');
    p=&g1;
    p->cry(); //输出: 我叫Gill,是男长颈鹿,脖子太长,发不出声音来!
    return 0;
}


3、每一个Animal的派生类都有一个“名字”数据成员,这一共有的成员完全可以由基类提供改造上面的程序,将这一数据成员作为抽象类Animal数据成员被各派生类使用。

#include "iostream"
#include<string>
using namespace std;
class Animal
{
    protected:
	string name;
public:
	Animal(string nam):name(nam){}
    virtual void cry() = 0;
};

class Mouse : public Animal
{
private:
    char sex;
public:
    Mouse(string nam, char s):Animal(nam),sex(s) {}
    virtual void cry()
    {
        cout<<"我叫"<<name<<",是一只"<<((sex=='m')?"男":"女")<<"老鼠,我的叫声是:吱吱吱!"<<endl;
    }
};

class Cat : public Animal
{
public:
    Cat(string nam):Animal(nam) {}
    virtual void cry()
    {
        cout<<"我叫"<<name<<",是一只猫,我的叫声是:喵喵喵!"<<endl;
    }
};

class Dog : public Animal
{
public:
    Dog(string nam):Animal(nam) {}
    virtual void cry()
    {
        cout<<"我叫"<<name<<",是一条狗,我的叫声是:汪汪汪!"<<endl;
    }
};

class Giraffe : public Animal
{
private:
    char sex;
public:
    Giraffe(string nam,char s):Animal(nam), sex(s) {}
    virtual void cry()
    {
        cout<<"我叫"<<name<<",是"<<((sex=='m')?"男":"女")<<"长颈鹿,我的脖子太长,发不出声音来!"<<endl;
    }
};

int main( )
{
    Animal *p;
//    p = new Animal();
//    p->cry(); //输出: 不知哪种动物,让我如何学叫?
    Mouse m1("Jerry",'m');
    p=&m1;
    p->cry(); //输出: 我叫Jerry,是一只男老鼠,我的叫声是:吱吱吱!
    Mouse m2("Jemmy",'f');
    p=&m2;
    p->cry(); //输出: 我叫Jemmy,是一只女老鼠,我的叫声是:吱吱吱!
    Cat c1("Tom");
    p=&c1;
    p->cry(); //输出: 我叫Tom,是一只猫猫,我的叫声是:喵喵喵!
    Dog d1("Droopy");
    p=&d1;
    p->cry(); //输出: 我叫Droopy,是一条狗狗,我的叫声是:汪汪汪!
    Giraffe g1("Gill",'m');
    p=&g1;
    p->cry(); //输出: 我叫Gill,是男长颈鹿,脖子太长,发不出声音来!
    return 0;
}




  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1.声明一个动物基类Animal,私有整型成员变量年龄age,请定义一个派生类Dog,在其成员函数SetAge(int n)中直接给age赋值,测试下看是否会出问题?如何解决? 2.设计一个单基继承的类层次程序,用Person类派生出Student类,增加属性学号index和年级level。Person类中至少有姓名name、年龄age等数据成员,以及构造函数、输出函数等,其余成员函数根据需要添加。在主函数中进行测试。 3.定义一个学生类Student和教师类Teacher,学生类有姓名name、学号index等数据成员,教师类有姓名name、工作证号workID、职称title、课程course、周学时hoursPerWeek等数据成员。再定义一个助教类TeachingAssistant,多继承于学生类和教师类,该类可以使用学生类的全部数据成员,以及教师类的课程和周学时数据成员。要求:每个类提供自定义的构造函数和析构函数,并通过同名函数ShowInfo来显示全部数据成员的值。在主函数中进行测试。 4.声明一个Person,包含姓名name和年龄age等私有数据成员以及相关的成员函数;由它派生出领导类Leader,包含职务position和部门department私有数据成员以及相关的成员函数;再由Person派生出工程师类Engineer,包含职务position和专业speciality私有数据成员以及相关的成员函数;再由Leader和Engineer类派生出主任工程师类Chairman。在主函数中测试各类对象初始化和信息输出,查看是否会出问题?如何解决?
C++ 中,我们可以使用串口类来进行串口通信。这里我们将自定义一个串口类,以便更好地理解串口通信的原理和实现。 首先,我们需要引入一些头文件: ```c++ #include <windows.h> #include <iostream> ``` 接着,我们定义一个串口类,其中包含了串口的打开、关闭、读取和写入等操作: ```c++ class SerialPort { public: SerialPort(); ~SerialPort(); bool Open(int portNo, int baudRate); bool Close(); int ReadData(char *buffer, unsigned int nbChar); bool WriteData(char *buffer, unsigned int nbChar); bool IsOpened() const; private: HANDLE m_hComm; bool m_bOpened; }; ``` 其中,m_hComm 是串口的句柄,m_bOpened 表示串口是否打开。 接下来,我们来实现这些操作。 首先是串口的打开操作: ```c++ bool SerialPort::Open(int portNo, int baudRate) { if (m_bOpened) { Close(); } char portName[50]; sprintf_s(portName, "\\\\.\\COM%d", portNo); m_hComm = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); if (m_hComm == INVALID_HANDLE_VALUE) { std::cerr << "Failed to open serial port!\n"; return false; } DCB dcb; GetCommState(m_hComm, &dcb); dcb.BaudRate = baudRate; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; if (!SetCommState(m_hComm, &dcb)) { std::cerr << "Failed to set serial port parameters!\n"; CloseHandle(m_hComm); return false; } m_bOpened = true; return true; } ``` 这里我们首先判断串口是否已经打开,如果已经打开则先关闭,然后根据串口号构建串口名称,并使用 CreateFile 函数打开串口。接着,我们设置串口的参数,包括波特率、数据位、校验位和停止位等。如果设置成功,则将 m_bOpened 设置为 true 并返回 true,否则返回 false。 接下来是串口的关闭操作: ```c++ bool SerialPort::Close() { if (!m_bOpened) { return true; } if (CloseHandle(m_hComm)) { m_bOpened = false; return true; } return false; } ``` 这里我们只需要调用 CloseHandle 函数关闭串口,并将 m_bOpened 设置为 false 即可。 接下来是串口的读取操作: ```c++ int SerialPort::ReadData(char *buffer, unsigned int nbChar) { DWORD bytesRead; if (!ReadFile(m_hComm, buffer, nbChar, &bytesRead, nullptr)) { std::cerr << "Failed to read data from serial port!\n"; return -1; } return bytesRead; } ``` 这里我们使用 ReadFile 函数从串口读取数据,并将读取的字节数存储在 bytesRead 变量中,并返回 bytesRead。 最后是串口的写入操作: ```c++ bool SerialPort::WriteData(char *buffer, unsigned int nbChar) { DWORD bytesSent; if (!WriteFile(m_hComm, buffer, nbChar, &bytesSent, nullptr)) { std::cerr << "Failed to write data to serial port!\n"; return false; } return true; } ``` 这里我们使用 WriteFile 函数将数据写入串口,并返回写入是否成功的结果。 最后,我们来实现一个判断串口是否打开的函数: ```c++ bool SerialPort::IsOpened() const { return m_bOpened; } ``` 这里只需要返回 m_bOpened 即可。 至此,我们就完成了一个简单的自定义串口类。可以通过实例化这个类来进行串口通信的操作,具体使用方法可以参考下面的示例代码: ```c++ int main() { SerialPort port; if (!port.Open(1, 9600)) { return -1; } char buffer[1024]; while (true) { int bytesRead = port.ReadData(buffer, sizeof(buffer)); if (bytesRead > 0) { buffer[bytesRead] = '\0'; std::cout << buffer << std::endl; } } port.Close(); return 0; } ``` 在这个示例中,我们首先实例化了一个 SerialPort 类,并通过 Open 函数打开了 COM1 号串口。然后,我们通过 ReadData 函数从串口读取数据,并将读取的数据打印到控制台上。最后,我们通过 Close 函数关闭了串口。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迂者-贺利坚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值