Hello everyone I am trying to get to know pointers better and I stumbled into a Qt type change. I have made a QString array and gave the pointer to the array to a method. But when I try to use a QString functions it give a error and says that it is a QCharRef which does not have the member function isEmpty().
The code:
QString data_array[2][3] =
{
{"11:28:8","Room 1","Presence detected"},
{"11:38:8","Room 1","No presence"}
}
bool method(QString *_data_array)
{
QString *data_array = _data_array;
return data_array[0][1].isEmpty(); /* changed to QCharRef */
}
My question is why does this happen and how can I prevent it or change it?
The reason for which you are getting QCharRef is due to how QString is built. The [] operator returns one character from a QString (QString is built up from QChars, much like strings in C/C++ are character arrays). From the Qt documentation:
The return value is of type QCharRef, a helper class for QString. When you get an object of type QCharRef, you can use it as if it were a QChar &. If you assign to it, the assignment will apply to the character in the QString from which you got the reference.
So what that means for you is that when you use the lovely square bracket operators, you are no longer using a QString, you are using a QChar reference.
As for how to change it, QChar's isNull() seems like it would fit your uses. so instead try return data_array[0][1].isNull(); and that should work.
I would also look into QStringList if you're doing things with lists of strings
Related
I have a QList which contains string, int, double and date values. I want to convert the QList to a QString and return it within a QString returning function. Is there a static function I can use or what am I missing here? My current code:
QString Product::toString()
{
QStringList listString;
QString outString;
for(int i =0; i < size(); i++)
{
listString << at(i)->toString();
}
outString = listString.join("\n");
return outString;
}
Notes:
I am assuming Product::at(int)is returning a Transaction, given a previous question.
I am also assuming OP mean "built-in" when he or she wrote"static"
The for can be removed using built-in functions. Some (many?) will find the new syntax less understandable, though.
QString Product::toString()
{
QStringList aggregate;
std::transform(m_transactions.begin(),
m_transactions.end(),
std::back_inserter(aggregate),
std::bind(std::mem_fn(&Transactions::toString), std::placeholders::_1));
// or : [](const Transaction& transaction){ return transaction.toString(); });
return aggregate.join("\n");
}
std::transform will transform every m_transactions elements using Transaction::toString(), and place the results into aggregate.
std::back_inserter means "use QStringList::push_bask to record the results". If QStringList had a resize(int) like QVector does, we could have used aggregate.begin() instead.
The unary function is a bit tricky, as it needs to be converted into a unary function, which what std::bind/std::mem_fn is doing. If you are using C++11, you can use a lambda instead.
Also from the previous question, #SingerOfTheFall's remark is valid:
I also find it a little odd to save transactions inside of products. A
better design would be having a separate class that could store them.
If you keep this design, Transaction Product::at(int) and int Product::size() should be renamed to make the link with Transaction explicit, like getTransaction and getNumberOfTransactions.
In C++ is perfectly legitimate to do:
bool x = "hi";
Because "hi" is translated by compiler to a char array and returns a pointer to that array, which is a number and number can be implicitly converted to bool (0 is false, anything else is true).
So I have these ctor:
Exception(QString Text, bool __IsRecoverable = true);
Exception(QString Text, QString _Source, bool __IsRecoverable = true);
Sadly I figured out that calling
Exception *e = new Exception("error happened", "main.cpp #test");
It creates a new instance of "Exception" class which is created using Exception(QString Text, bool __IsRecoverable = true); constructor, which is wrong to a point.
Is there a simple way to ensure that correct function is called, other than restructuring the constructors entirely, changing position of arguments, etc?
Firstly, I'm not sure why you're dynamically allocating an exception class. I'm not sure that's ever a good idea.
You can explicitly construct a QString:
Exception e("error happened", QString("main.cpp #test"));
Or you can pass the third argument:
Exception e("error happened", "main.cpp #test", true);
Or you can add an additional constructor that takes const char* and will be preferred over the conversion to bool:
Exception(QString Text, const char* Source, bool IsRecoverable = true);
You can easily make this forward to the QString version. Also note that names beginning with an underscore and a capital letter or with two underscores are reserved.
My suggestion would be to not use default arguments. They contribute to overload resolution problems like this, and anyway it is not very readable to just see true as an argument. Whoever's reading the code then has to stop and go look up what the true means. Even if it's yourself you may forget it in a few months time when you come back to the code, especially if you do this sort of thing a lot.
For example:
struct Exception: public whatever
{
Exception(char const *text);
Exception(char const *text, char const *source);
};
struct RecoverableException: public Exception
{
RecoverableException(char const *text);
RecoverableException(char const *text, char const *source);
};
It's a little bit more typing in this source file but the payoff is that your code which actually uses the exceptions is simpler and clearer.
To implement these constructors you could have them all call a particular function in the .cpp file with relevant arguments selecting which behaviour you want.
I have a preference for using char const * rather than QString as I am paranoid about two things:
unwanted conversions
memory allocation failure
If constructing a QString throws then things go downhill fast. But you may choose to not worry about this possibility because if the system ran out of memory and your exception handling doesn't prepare for that possibility then it's going to terminate either way.
I'm trying to make a function that replace the text inside a QLineEdit when the user want to revert is name to default using a QPushButton.
This is where the code is getting "saved".
`//Must get information in the DB
lineditPlayerName = new QLineEdit("Nouveau Profil");
nameAsDefault = new QString(lineditPlayerName->text());
languageAsDefault = new QString(comboBoxlanguage->currentText());`
This is the function i use to change the value back to default
//This code works
void ProfileManager::revertName(){
lineditPlayerName->setText("nameAsDefault");
btnRevertName->setEnabled(false);
}
But I need it like this :
//This code does'nt
void ProfileManager::revertName(){
lineditPlayerName->setText(NameAsDefault);
btnRevertName->setEnabled(false);
}
I can't get it to work it give's me this error:
no matching function for call to 'QLineEdit::setText(QString*&)'
Thanks
You must dereference the NameAsDefault variable
void ProfileManager::revertName(){
lineditPlayerName->setText(*NameAsDefault);
// ^ Here I dereferenced the pointer
btnRevertName->setEnabled(false);
}
The type of nameAsDefault is pointer to a QString. However QLineEdit::setText expects a QString object, not a pointer. Therefore the compiler tells you that there is no function which expects a pointer.
I did not see your declaration of the nameAsDefault variable, but since
nameAsDefault = new QString(lineditPlayerName->text());
compiles and new returns a pointer, I suppose it is a pointer.
Also, what is probably more important is that you should almost never allocate objects using new. Especially not objects from the Qt library, which are implicitly shared.
I got some problems in creating my program for mobile using QT C++
When i run it i get this: cannot convert 'std::string' to 'std::string*' in initialization
And theres code for that error:
void rozvrh_b17::pars(string par)
{
data = new std::string*(par);
printf(data->data());
}
//data and par are std::string
//without that new std::string*() it does similiar error
And i ask how to convert std::string to std::string* ??
EDIT:
i made this function to transfer data from one form to another and i need to remember that parameter...
I downvoted you because this question shows no research effort.
string * data = ∥
std::string* is a pointer type. You have a std::string, and it's address is the pointer type you want. This is one of the first principles of using pointers.
What do you really try to do?
If you just want to print the string then this should work:
void rozvrh_b17::pars(string par)
{
printf(par.c_str());
}
If you want to create a copy of string on the heap then you need this:
std::string* data = new std::string(par);
but that doesn't make much sense.
You are trying to assign a string from a pointer to string. In this particular case I see several things.
You don't need a copy at all - simply use par right away
You better make par a const ref: void rozvrh_b17::pars(const string& par)
You should use only string whaen calling new otherwise you create a pointer to string. So do: data = new std::string(par);
Well, what i want is to implement functions that works like the macros SIGNAL and SLOT but with my own implementation, so the goal is that the function (or my own macro if i can create it) receive a parameter like an String "mycustomsignal" and he return a const char* "2mycustomsignal(double,int)" so i do that using a QMap for store this asociation QMap<"signal name","signal signature">, i fill it in another function.
in this case my QMap is this->signals so i search the signature "mycustomsignal(something)" with the key "mycustomsignal" and prepend the code that QObject::connect recognize for signals and i get "2mycustomsignal(something)" so i convert it in const char* because QObject::connect have this parameters in this format and i want to use also in conjuntion with SIGNAL and SLOT MACROS like this:
QObject::connect(customwidget, customwidget->getSignal("somesignal"),
somewidget, SLOT(someslot()));
the function that i use is (only for undertand what i do):
const char* SomeClass::getSignal(QString signalName) {
QString signalsignature = this->signals.value(signalName);
signalsignature.prepend(QString::number(QSIGNAL_CODE));
QByteArray ba = signalsignature.toLatin1();
return signalformated; //Here is the lost of data because QByteArray only exist in the function
}
but this return a pointer to local and the source of the data is destroyed when the function ends, so how i could do this with a function or creating my own MACRO?
Thanks for any help or suggestion.
You have to return QByteArray from your method, return ba;, then get the const char* from the return value:
QObject::connect(customwidget, customwidget->getSignal("somesignal").constData(),
somewidget, SLOT(someslot()));
If you really want to return char pointer, then you have to keep the QByteArray around, for example by adding it to a QList member variable of the same object, so it will get destructed when the instance gets destructed.