【问题标题】:c++ inheritance Qt problem qstringc++继承Qt问题qstring
【发布时间】:2010-11-01 12:04:51
【问题描述】:

我有以下代码:

template <class T>
bool loadCSV (const QString &filename, map<T,int> &mapping){
    QFile boxfile;
    boxfile.setFileName(filename);
    QString line;
    QStringList list;

    if (!boxfile.open(QIODevice::ReadOnly)){
        cout << "Could not open box data file." << endl;
        return false;
    }

    QTextStream stream2( &boxfile ); 

    while (!stream2.atEnd()){
        line = stream2.readLine();
        list = line.split(',');
        mapping[list.front().toInt()]=list.back().toInt();      
    }

    return true;
}

它需要一个 CSV 文件并将其粘贴到:

map<int, int> mapping

结构。现在这是作为模板完成的,因此我也可以使用将数据粘贴到

map<string, int> mapping

结构。现在要做到这一点,需要更改 while 循环中的最后一行,我不确定实现这一点的最佳方法是什么。

我可以想到几个方法:

  1. 一些如何检测类型并在其中有某种条件行(我实际上不确定这是否可行,如果可以,该怎么做。

  2. 向 QStringList 添加一个类函数来执行此操作。

我尝试了选项 2 并做到了:

void QStringList::cInsert(map<int,int> &mapping){
    mapping[this->front().toInt()]=this->back().toInt();
}

void QStringList::cInsert(map<string,int> &mapping){
    mapping[(this->front()).toAscii()]=this->back().toInt();
}

这不起作用,因为我还需要在 QStringList 类中定义这些函数,所以这会有点混乱。反而。我尝试从 QStringList 继承:

class myQStringList: public QStringList{
    public:
        void cInsert(map<int,int> &mapping);
        void cInsert(map<string,int> &mapping);
};

void myQStringList::cInsert(map<int,int> &mapping){
    mapping[this->front().toInt()]=this->back().toInt();
}

void myQStringList::cInsert(map<string,int> &mapping){
    mapping[(this->front()).toAscii()]=this->back().toInt();
}

然后改代码:

template <class T>
bool loadCSV (const QString &filename, map<T,int> &mapping){
    QFile boxfile;
    boxfile.setFileName(filename);
    QString line;
    myQStringList list;   

if (!boxfile.open(QIODevice::ReadOnly)){
    cout << "Could not open box data file." << endl;
    return false;
}

QTextStream stream2( &boxfile ); 

while (!stream2.atEnd()){
    line = stream2.readLine();
    list = line.split(',');
        list.cInsert(mapping);
}

return true;}

但是。我收到与 line.split/list 分配有关的错误:

main.cpp:123: error: no match for 'operator=' in 'list = QString::split(const QChar&, QString::SplitBehavior, Qt::CaseSensitivity) const(((const QChar&)(&QChar(44))),  KeepEmptyParts,  CaseSensitive)'

我不确定这个错误是什么,也不确定它是否与未继承的分配/复制运算符有关?

关于实际的新类,我收到此错误:

main.cpp:104: error: no match for 'operator[]' in 'mapping[QString::toAscii() const()]'
c:/qt/mingw/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_map.h:332: note: candidates are: _Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = std::string, _Tp = int, _Compare = std::less<std::string>, _Alloc = std::allocator<std::pair<const std::string, int> >]
main.cpp: In function `bool loadCSV(const QString&, std::map<T, int, std::less<_Key>, std::allocator<std::pair<const T,int> > >&) [with T = int]':

我就是不明白。谁能解释一下?

另外,我不确定我处理这件事的方式是否正确,并且也希望得到与此相关的建议。谢谢。

【问题讨论】:

    标签: c++ inheritance qt4


    【解决方案1】:

    我会将转换从 QString 移到函数之外的类型 T。因此,有类似的东西:

    template< typename T>
    struct converter { };
    
    template<>
    struct converter< int>
    {
    static int convert( const QString& source)
    {
        return source.toInt();
    }
    };
    
    template<>
    struct converter< std::string>
    {
    static std::string convert( const QString& source)
    {
        return source.toStdString();
    }
    };
    
    template< typename T>
    T convertFromString( const QString& source)
    {
        return converter<T>::convert( source);
    }
    

    然后,在循环中使用这个转换函数(在 while 内):

    代替

    mapping[list.front().toInt()]=list.back().toInt();   
    

    写:

    mapping[ convert<T>(list.front())]=list.back().toInt();
    

    注意: 定义了类转换器(及其两个特化),因此可以将 convert 函数用作模板函数(类似于 static_cast 或 boost::lexical_cast,如果您愿意)。

    我没有尝试编译代码。这只是一个想法。

    【讨论】:

      【解决方案2】:

      对于 CSV 文件,Qt 通过 QString::section 函数提供了简洁的功能。因此,为了找出必要的列,我按如下方式处理标题:

      int AmountInd = (line.left(line.indexOf("Amount")).count(',');
      

      获取该列的索引。然后,对于即将到来的行,我提取该列的子字符串:

      QString AmountStr = (line.section(',', AmountInd, AmountInd);
      double Amount = AmountStr.toDouble();
      

      希望您会发现部分功能有用 ;-)

      【讨论】:

        【解决方案3】:

        我通过显式转换解决了这个问题:

        list = (const myQStringList&) line.split(',');
        void myQStringList::cInsert(map<string,int> &mapping){
            mapping[(string)(this->front()).toAscii()]=this->back().toInt();
        }
        

        【讨论】:

        • 你也有 QString::toStdString() 方法。还有 QString::fromStdString() ......
        • C++ 程序中的 C 风格转换是邪恶的。您可以改用 static_cast .. 或 dynamic, reinterpret 和 const_cast ,具体取决于您的目的。与 Qt C++ 程序中的 qobject_cast 和 qvariant_cast 一起使用。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-11
        • 2011-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多