Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过重写非虚方法对QIODevice进行子类化_C++_Qt_Inheritance_Virtual Functions - Fatal编程技术网

C++ 通过重写非虚方法对QIODevice进行子类化

C++ 通过重写非虚方法对QIODevice进行子类化,c++,qt,inheritance,virtual-functions,C++,Qt,Inheritance,Virtual Functions,我想从QIODevice中创建子类,因为我正在创建我的自定义设备(自定义串行端口对象) 我看到: writeData(const char *, qint64 ) : qint64 readData(char *, qint64 ) : qint64 在QIODevice接口中声明为虚拟,但不是方法: read(char *, qint64 ) : qint64 write(const char *, qint64 ) : qint64 然后在我的项目中,我有一个串行端口管理器类,如下所示:

我想从QIODevice中创建子类,因为我正在创建我的自定义设备(自定义串行端口对象)

我看到:

writeData(const char *, qint64 ) : qint64
readData(char *, qint64 ) : qint64
在QIODevice接口中声明为虚拟,但不是方法:

read(char *, qint64 ) : qint64
write(const char *, qint64 ) : qint64
然后在我的项目中,我有一个串行端口管理器类,如下所示:

class SerialPortManager{
public:
    SerialPortManager(int type){
         if (type == 1)
             genericSerialPort = new QSerialPort(); //QT framework
         else if (type == 2)
             genericSerialPort = new MySerialPort(); //my custom object, derived from QIODevice
    }

    qint64 write(char * data, qint64 size)
    {
        genericSerialPort->write(data, size);
    }    

private:
    QIODevice* genericSerialPort = 0;
};
class MySerialPort : public QIODevice{
    Q_OBJECT
    public:
        explicit MySerialPort(QObject *parent = Q_NULLPTR);
        virtual ~MySerialPort();

        qint64 readData(char *data, qint64 maxSize);
        qint64 writeData(const char *data, qint64 maxSize);

        qint64 write(char * data, qint64 size);

        ...
    };
我的自定义串行端口(MySerialPort.h)定义如下:

class SerialPortManager{
public:
    SerialPortManager(int type){
         if (type == 1)
             genericSerialPort = new QSerialPort(); //QT framework
         else if (type == 2)
             genericSerialPort = new MySerialPort(); //my custom object, derived from QIODevice
    }

    qint64 write(char * data, qint64 size)
    {
        genericSerialPort->write(data, size);
    }    

private:
    QIODevice* genericSerialPort = 0;
};
class MySerialPort : public QIODevice{
    Q_OBJECT
    public:
        explicit MySerialPort(QObject *parent = Q_NULLPTR);
        virtual ~MySerialPort();

        qint64 readData(char *data, qint64 maxSize);
        qint64 writeData(const char *data, qint64 maxSize);

        qint64 write(char * data, qint64 size);

        ...
    };
这里发生的事情是,如果我创建一个类型为1(
QSerialPort
实例)的
SerialPortManager
对象,并对其调用
write
,则调用
QSerialPort
上的
write
函数。 相反,如果我创建了一个类型为2的
SerialPortManager
对象(
MySerialPort
实例),并在其上调用
write
,则不会调用
write
函数

那么,是否可以覆盖
QIODevice
的非虚拟方法
write

否则,如果
write
read
不是虚拟的,如何创建自定义
QIODevice
。如果写入和读取不是虚拟的,则不会覆盖它们

readData
writeData
是纯虚拟的,受保护。所以我假设
write
read
将在内部调用这些函数

至于为什么它们不可重写,您必须询问Qt设计者。它们很可能修改一些内部状态等,这些状态是私有的,因此必须在这些调用中进行包装


通常,Qt类设计得非常好,因此我假设您首先不需要重写
write
read
。如果您这样做,您的设计可能会有一些问题。

这是由设计完成的。如果写入和读取不是虚拟的,则不会覆盖它们

readData
writeData
是纯虚拟的,受保护。所以我假设
write
read
将在内部调用这些函数

至于为什么它们不可重写,您必须询问Qt设计者。它们很可能修改一些内部状态等,这些状态是私有的,因此必须在这些调用中进行包装



通常,Qt类设计得非常好,因此我假设您首先不需要重写
write
read
。如果您这样做,您的设计可能会出现一些问题。

您无法覆盖非虚拟方法,只能对它们进行阴影处理,这是没有帮助的。您必须重写write_数据,而不是write(您不能这样做)。@n.m.假设我重写just writeData方法。如果我在我的对象上调用write,会发生什么?如果基类在其write方法上调用我的writeData实现,是否调用了它?文档就是这样记录的。“如果基类在其写方法上调用我的writeData实现,是否调用了它?”是的,这就是writeData是虚拟的。如果没有Qt的调试构建,您将一事无成。一旦有了它,就可以使用它来跟踪调用'QIODevice::read'或'write'时发生的事情。那你就会明白了。真的。你不能覆盖非虚拟方法,你只能对它们进行阴影处理,这是没有用的。您必须重写write_数据,而不是write(您不能这样做)。@n.m.假设我重写just writeData方法。如果我在我的对象上调用write,会发生什么?如果基类在其write方法上调用我的writeData实现,是否调用了它?文档就是这样记录的。“如果基类在其写方法上调用我的writeData实现,是否调用了它?”是的,这就是writeData是虚拟的。如果没有Qt的调试构建,您将一事无成。一旦有了它,就可以使用它来跟踪调用'QIODevice::read'或'write'时发生的事情。那你就会明白了。真的。好的,但如果我在对象上调用read或write方法,则不会调用重写的writeData和readData。一般来说,如果我在类上调用read,则基类的read被调用,对吗?然后,在其实现上,假设它调用虚拟readData。它是基于还是派生的readData?您是否已打开设备并处于读/写模式?在实际进行写/读操作之前,您可能会遇到错误。检查write/read的返回值,并使用
errorString()
检查错误您的类中不应该有
read
函数。所以它只有基类函数
QIODevice
本身没有
readData
(它是纯虚拟的),因此将调用您的。但是根据基本的OO原则,派生的函数将被调用。如果你不确定什么时候用虚拟函数调用什么函数并覆盖它们,我想最好编写一些小程序(没有qt,只有一些类),然后自己尝试一下。这有助于理解其工作原理。好的,但如果我在对象上调用read或write方法,则不会调用重写的writeData和readData。一般来说,如果我在类上调用read,则基类的read被调用,对吗?然后,在其实现上,假设它调用虚拟readData。它是基于还是派生的readData?您是否已打开设备并处于读/写模式?在实际进行写/读操作之前,您可能会遇到错误。检查write/read的返回值,并使用
errorString()
检查错误您的类中不应该有
read
函数。所以它只有基类函数
QIODevice
本身没有
readData
(它是纯虚拟的),因此将调用您的。但是根据基本的OO原则,派生的函数将被调用。如果你不确定什么时候用虚拟函数调用什么函数并覆盖它们,我想最好编写一些小程序(没有qt,只有一些类),然后自己尝试一下。这有助于理解其工作原理。