新项目又快开始了,一个项目一种语言,这酸爽,真是本屌程序猿才能体会的啊。这次使用Qt,尼玛对于本屌这种一直使用Java,C++基础薄弱的程序猿来说还是有点难度,毕竟C++与Java、C#还是有些差别,一时半会儿还得适应。项目还没开始,在学习Qt的过程中自己构想几个例子来试手,也把使用过程中碰到的问题记录下来,可能都是一些非常非常基础的知识了(大虾莫喷,有好的方法请不吝赐教),但对于我这种没C++经验的程序猿还是要花一时半会儿才能解决,先把这些问题和解决方法都记录下来,供以后查阅吧。
1、使用QSqlQuery的bindValue方法编译出错,报no matching function for call to 'QSqlQuery::bindValue(const char [6], QString)'
报错代码:query.bindValue(":type", "类型");
看了书上的例子和Qt文档中的例子都是这样写的啊,语法没有错误啊。搞了半天原来是bindValue的第二个参数QVariant类型,cpp文件中没有QVariant的引用,
把#include <QVariant>加上就ok了,经验值加1,以后碰到这种问题就有经验处理了。
2、 出现field 'm_createDate' has incomplete type错误。
报错代码:头文件声明QDateTime m_createDate;出错
报未完成的类型错误,由于只在头文件中加了class声明,如class QDateTime,在cpp文件中也使用#include <QDateTime>将该类引入,但由于使用QDateTime m_createDate;方式为创建了QDateTime对象,但由于只是对QDateTime类进行了声明而隐藏了类的实现,此时编译时不知道QDateTime的完成实现所以无法创建QDateTime对象。
解决办法有两种:
(1)在头文件中使用#include <QDateTime>方式替换class QDateTime;
(2)将QDateTime m_createDate;改为QDateTime *m_createDate;然后在构造函数中初始化该指针,在析构函数中删除该指针。使用指针的方式创建该对象的指向地址,而地址为数值所以无需知道QDateTime的完整实现。
3、QT绘图抗锯齿设置
QT中对于绘图抗锯齿的设置使用QPainter的setRenderHint()方法,具体设置为
painter->setRenderHint(QPainter::Antialiasing);
4、error: jump to case label case CData::INT:
error: crosses initialization of 'QByteArray array'
在使用switch语句时,编译时出现以上错误提示未初始化array变量。但是在case分支中对array进行了初始化,如下代码:
switch(type)
{
case CData::BYTEARRAY:
QByteArray array;
break;
case CData::INT:
qDebug() << "key:"<< it.key() << ",value:" << it.value()->getInt();
break;
}
修改代码,将array变量的定义放在switch外部即可。
5、编译时遇到*** No rule to make target 'xxx.cpp', needed by 'debug/xxx.o'. Stop.问题
出现该问题的原因为,在.pro文件中包含了某.cpp文件和.h文件,但是在项目中可能因为该文件未被使用,在本地直接删掉了该文件,而.pro文件中还包含了这两个文件的引用,此时编译就会出现以上问题。解决办法是在.pro文件中删除“xxx.cpp”和“xxx.h”的引用即可。
6、C++中求数组长度
在C++中没有包含对数组求长度的函数,只提供了一个strlen用于求字符串长度的函数。如果需要对其他类型的数组求长度,需采用如下方法:
int length = sizeof(array) / sizeof(array[0])
这里的array为任意类型的数组。
7、调用自定义的库,编译时出现:undefined reference to `_imp___ZN10CConverter10byteToCharE10QByteArray'
今天在调用自己写的库,编译时出现标题的错误提示,大概含义是CConverter类中未找到byteToChar的实现。找了半天,原来是.cpp文件中该方法前忘了加“CConverter::”,真是折腾了半天。记下,再不要这么粗心大意!
8、error: '>>' should be '> >' within a nested template argument list QMap<QString, QList<CProtocolDom>> *m_protocolMap;
QT中在定义列表或map中嵌套列表或map时,需要注意的是,两个尖括号之间需要加上一个空格,否则编译就出现如题所述错误。QMap<QString, QList<CProtocolDom>> *m_protocolMap; //错误代码
QMap<QString, QList<CProtocolDom> > *m_protocolMap; //正确代码
^增加了一个空格
9、C++中对类型的判断
在C++中对对象类型的判断使用typeid运算符,相当于java中instanceof关键字。但用法不一样。typeid表达式形式为typeid(e),其中e可以是任意表达式或类型名字。typeid操作的结果是一个常量对象的引用,该对象的类型是标准库类型type_info或者type_info的共有派生类型。type_info类定义在typeinfo头文件中,所以在使用typeid运算符时需要将typeinfo头文件引入程序中。
使用方法示例:
CData data;
bool is = typeid(data) == typeid(CData);
// is = true
CData* data = new CData;
bool is = typeid(data) == typeid(CData);
//这样输出永远为false,因为data是一个地址,typeid是作用于对象。正确做法为如下代码:
CData* data = new CData;
bool is = typeid(*data) == typeid(CData);
10、关于QT中容器元素的内存释放问题
在编程中很多时候会使用到容器(如QMap、QList)来存放自己所需的数据,这里就涉及到对容器中存储的数据的内存释放问题。这里测试了几行代码,留下来方便以后的查看和理解。
第一种情况,容器中存放的为new出来的数据,需手动释放其内存
QMap<QString, CTestClass*>* map = new QMap<QString, CTestClass*>;
CTestClass* tc1 = new CTestClass;
CTestClass* tc2 = new CTestClass;
CTestClass* tc3 = new CTestClass;
map->insert("1", tc1);
map->insert("2", tc2);
map->insert("3", tc3);
delete map;//这样只能释放掉map,而map中的CTestClass并不能得到释放
QList<CTestClass*>* list = new QList<CTestClass*>;
CTestClass *item1 = new CTestClass;
CTestClass *item2 = new CTestClass;
CTestClass *item3 = new CTestClass;
list->append(item1);
list->append(item2);
list->append(item3);
delete list;//这样只能释放掉list的内存,而list中的CTestClass也不能得到释放
第二种情况,容器中存放的为数据对象,这些对象的内存由容器统一管理,当对象脱离了容器或容器释放时,容器内的对象内存也得到相应的释放
QMap<QString, CTestClass>* map_1 = new QMap<QString, CTestClass>;
CTestClass tc1_1;
CTestClass tc2_1;
CTestClass tc3_1;
map_1->insert("1", tc1_1);
map_1->insert("2", tc2_1);
map_1->insert("3", tc3_1);
delete map_1;//释放map_1、map->remove("1")或map->clear(),map中的对象内存都会得到释放
QList<CTestClass>* list_1 = new QList<CTestClass>;
CTestClass item1_1;
CTestClass item2_1;
CTestClass item3_1;
list_1->append(item1_1);
list_1->append(item2_1);
list_1->append(item3_1);
delete list_1;
CTestClass类:
#include <QDebug>
#include "ctestclass.h"
CTestClass::CTestClass()
{
}
CTestClass::~CTestClass()
{
qDebug() << "delete CTestClass!";
}
11、释放未初始化指针
12、new int[10]和new int[10]()的区别
12、LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
使用MSVC编译器编译项目时出现:LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
可能出现问题的原因:在项目中包含了其他库,而这些库是release版本的,在使用qt构建时使用的debug模式,这样就出现了如题所示的编译错误,将模式切换成release版本就没有问题了