Strange problem, already looked into with several colleagues...
Using Qt Creator and Qt 4.8.5
define an object
set a number of values with setters
request values with a getters
result: getting an int no problem, all other values give segmentation fault
but with breakpoint in debugger the values are correctly shown, so they are in the object!
same code worked before, problem "just appeared". Compiler issue?
private:
int id;
QString name;
public;
int getId() { return this->id; } // OK
void setId(int id) { this->id = id; }
QString getName() { return this->name; } // SIGSEGV
void setName(QString name) { this->name = name; }
Any ideas? Same issue known?
UPDATE
Changed code to this, based on comments, still same issue
private:
int id;
QString name;
public;
int getId() { return id; } // OK
void setId(int setTo) { id = setTo; }
QString getName() { return name; } // SIGSEGV
void setName(QString setTo) { name = setTo; }
I was facing similar issue. Although I could not find the root cause of this issue, I have another observation.
If we define the getter functions outside the class declaration using scope resolution operator the code works.
QString MyClass::GetX(void) {
return mX;
}
QString MyClass::GetY(void) {
return mY;
}
class MyClass
{
public:
MyClass(){}
/* Functions for setting mX and mY strings. */
QString GetX(void);
QString GetY(void);
isDataAvailable()
{
return mAvailable;
}
private:
bool mAvailable;
QString mX;
QString mY;
};
As I understand, in C++, if we define a function within class declaration, by default it is inline... so the issue could be something related with inlining of the functions.
thinking further about the way objects are created in memory, I thought that a QString maybe doesn't reserve fixed number of bytes, which could be the cause of this strange behavior and guess what, a dummy change solved my problem...
This feels like a really "dirty" solution, but at least I can go on with my work ;-)
But any idea's on the root cause would really be appreciated! Thanks already for all the valuable comments!!!
private:
QString name; // FIRST DEFINE QSTRING
int id; // THEN DEFINE INT
public;
int getId() { return id; } // OK
void setId(int setTo) { id = setTo; }
QString getName() { return name; } // OK
void setName(QString setTo) { name = setTo; }
Related
I was working on homework that my instructor wanted me to write a class named Species with setter and getter functions. I wrote that code but I can't set or get any value when I run it. Can you help me?
class Species
{
private:
string name;
string country;
int population;
int growthrate;
public:
int year;
void setName(string NameS){
NameS=name;
}
void setCountry(string CountryS){
CountryS=country;
}
void setPopulation(int pop){
pop=population;
}
void setGrowthRate(int GrowRth){
GrowRth=growthrate;
}
void setYear(int syear){
syear=year;
}
string getName() {
return name;
}
string getCountry() {
return country;
}
int getPopulation() {
return population;
}
int getGrowthrate() {
return growthrate;
}
double e=2.71828182;
double calculatePopulation() {
int b=growthrate*year;
int a=pow(e,b);
return population*a;
}
};
First of all. Your class has fields like:
string name;
string country;
int population;
int growthrate;
And your methods are like:
void setName(string NameS){
NameS=name;
}
So you want to set NameS value to the name which makes no sense.
You should assign the field like name to be equal to nameS not the opposite.
Generally, a setter should look like this.
void setVariable(const VariableType& var){
this->var=var;
}
What you did was var=this->var.
Btw, you should make your getter-s const
You should use "this" keyword to set the value to object of the class.
this: to refer current class instance variable. The this keyword can be used to refer current class instance variable.
for example:
void setName(string name){
this.name=name;
}
void setGrowthRate(int growthrate){
this.growthrate=growthrate;
"this" is very helpful in please learn more about it.
I added some exception handling into some functions in my Project. Before adding the error handling the program was working normally. After adding the exceptions I now get garbage values in the constructor and mutator parameters and I'm not sure where its coming from. Some of the functions are called in no other location than the constructor, so I have no idea where they are getting the garbage data from.
I also checked for memory leaks with valgrind and some debugging with gdb, but didn't find anything. I'm at my wits end. I have attached a sample of the constructor cpp below and one of the mutators with the exception handling.
Protofield.cpp
ProtoField::ProtoField(std::string t_name, std::string t_abbreviation, FieldType t_type, Base t_base, int t_mask, std::string t_description, int t_offset, int t_length){
try{
setName(t_name);
setAbbreviation(t_abbreviation);
setType(t_type);
setBase(t_base);
setMask(t_mask);
setDescription(t_description);
setOffset(t_offset);
setLength(t_length);
m_valueString = std::map<int, std::string>();
}
catch(std::runtime_error e){
std::cerr<<"Error in ProtoField Constructor"<<std::endl;
std::cerr<<e.what()<<std::endl;
return;
}
}
/*Removed for brevity*/
void ProtoField::setMask(int t_mask){
if(mask != 0){
std::stringstream ss;
ss<<"Field " << m_abbreviation << " mask previously set: "<<m_mask;
throw std::runtime_error(ss.str());
}
else{
m_mask = t_mask;
}
return;
}
/*Removed for brevity*/
ProtoField.hpp
class ProtoField{
private:
std::string m_name;
std::string m_abbreviation;
FieldType m_type;
Base m_base;
int m_mask;
std::string m_description;
int m_offset;
int m_length;
std::map<int, std::string> m_valueString;
public:
ProtoField(
std::string t_name = "",
std::string t_abbreviation = "",
FieldType t_type = FieldType::ft_invalid,
Base t_base = Base::invalid,
int t_mask = 0,
std::string t_description = "",
int t_offset = -1,
int t_length = -1
);
std::string getName();
std::string getAbbreviation();
FieldType getType();
Base getBase();
int getMask();
std::string getDescription();
int getOffset();
int getLength();
std::map<int, std::string> getValueString();
void setName(std::string t_name);
void setAbbreviation(std::string t_abbreviation);
void setType(FieldType t_type);
void setType(std::string t_typestr);
void setBase(Base t_base);
void setBase(std::string t_basestr);
void setMask(int t_mask);
void setDescription(std::string t_description);
void setOffset(int t_offset);
void setLength(int t_length);
void addValueString(int t_key, std::string t_value);
void removeValueString(int t_key);
//other functions
std::string to_string();
};
I feel as though its also worth mentioning, only integers appear to be affected. The other values including strings and enums seem to remain consistent with their previous behaviors. So in the class shown, only the mask, offset, and length show odd behaviors.
Edit: For more detail where the constructor is called I included the two functions I know of here.
void parser::parseFields(ProtoData& t_data, ptree::ptree t_subtree){
try{
std::vector<ProtoField> fields;
for(auto val : t_subtree.get_child("")){
ProtoField field;
parseField(t_data, field, val.second);
fields.push_back(field);
}
for(auto field:fields){
t_data.addField(field);
}
}
catch(ptree::ptree_bad_path error){
std::cerr<<"Bad Path to Fields"<<std::endl;
}
catch(ptree::ptree_bad_data error){
std::cerr<<"Bad Data to fields"<<std::endl;
}
}
void parser::parseField(ProtoData& t_data, ProtoField& t_field, ptree::ptree t_subtree){
try{
t_field.setAbbreviation(t_subtree.get<std::string>("abbreviation"));
t_field.setName(t_data.getName() + "_" + t_field.getAbbreviation());
t_field.setBase(t_subtree.get<std::string>("base", "none"));
t_field.setType(t_subtree.get<std::string>("type"));
}
catch(ptree::ptree_bad_path error){
std::cerr<<"Bad Path to Field"<<std::endl;
}
catch(ptree::ptree_bad_data error){
std::cerr<<"Bad Data to field"<<std::endl;
}
}
Your constructor does not initialize m_mask. You then call setMask, which reads this yet-to-be-initialzed value (assuming that the if(mask != 0) line should be if(m_mask != 0)). This is Undefined Behavior. The value read could be anything. When it is a nonzero value, the exception will be thrown.
The solution is to either initialize m_mask before calling setMask, or assign to m_mask directly in the constructor and not call the helper function. (And since the constructor sets the mask, which can only be done once, why does that function even need to exist?)
I created a singleton class
class AreaDataRepository {
private:
AreaDataRepository();
AreaDataRepository(const AreaDataRepository& orig);
virtual ~AreaDataRepository();
Way onGoingWay;
public:
static AreaDataRepository& Instance()
{
static AreaDataRepository singleton;
return singleton;
}
void SetOnGoingWay(Way onGoingWay);
Way const & GetOnGoingWay() const;
};
void AreaDataRepository::SetOnGoingWay(Way onGoingWay) {
this->onGoingWay = onGoingWay;
}
Way const & AreaDataRepository::GetOnGoingWay() const {
return onGoingWay;
}
header file of Way
class Way {
private:
std::string id;
std::string name;
public:
Way();
Way(const Way& orig);
virtual ~Way();
void SetName(std::string name);
std::string const & GetName() const;
void SetId(std::string id);
std::string const & GetId() const;
};
Then i'm created a Way object and set vales of id and name.
Way wayNode;
wayNode.SetId("123");
wayNode.SetName("jan")
AreaDataRepository::Instance().SetOnGoingWay(wayNode);
After assign OngoingWay accessing it from another class.
std::cout << AreaDataRepository::Instance().GetOnGoingWay().GetId();
the vale is not printing.
I'm going psychic here.... and I divine that your implementation of SetId is like this:
void SetId(std::string id) { id = id; }
that does not set the member variable, that sets the parameter to itself. And since your constructor most likely set the member variable id to "" you're printing empty strings. Either change the name of the parameter (to newId for example) to avoid the conflict or change the implementation to:
void SetId(std::string id) { this->id = id; }
As proof of this claim here's the result for the first version, as you see it prints nothing. And here is the result for the second, as you can see it prints the number.
The problem boils down to this: you have function parameter names that are the same as the name of your member variables and the function parameters are shadowing/hiding the member variables.
The only place this cannot happen is in a constructor's initialization list:
class Foo {
int x;
public:
Foo(int x): x(x) {} // <-- this works
void SetX(int x) { x = x; } // <-- this won't the parameter is hiding the member variable
};
Demo for the above snippet
std::cout is buffered in most implementations, if not in all. That means, the stream will wait for you to end a line before writing out any data. So, you can easily fix this by changing your output statement to
std::cout << AreaDataRepository::Instance().GetOnGoingWay().GetId() << std::endl;
I recently came across this class and was surprised at how the getters and
setters were implemented.
I have not come across this before and would welcome some second opinions.
Do you think this is a good paradigm?
Is is bad?
Is it evil?
Header:
class Tool
{
public:
Tool();
virtual ~Tool();
bool setName(const std::string &name);
bool getName(std::string &name) const;
void clearName();
private:
std::string m_name;
bool m_nameSet;
};
cpp file:
#include "Tool.h"
Tool::Tool()
: m_name("")
, m_nameSet(false)
{
}
Tool::~Tool()
{
}
bool Tool::setName(const std::string &name)
{
m_name = name;
m_nameSet = true;
return (m_nameSet);
}
bool Tool::getName(std::string &name) const
{
bool success = false;
if (m_nameSet)
{
name = m_name;
success = true;
}
return (success);
}
The way you selected for getter is not popular, programmers prefer to return data from getter
std::string getName() const;
Why an item that set before, or has an initial data, should be re-checked on getter? If you want validate the data, validate it on setter.
However if your insist to return a value as "is name set before", you can write a third method by means of bool isNameSet() const;
This looks a lot like C where it is usual to return status codes to see if a functions fails or not.
Then also there are better methods to verify that a name is set or not. One could be to use the boost::optional to me this is a better way to declare intent that the name might not be set at all times.
I would however wonder if it's not better to make sure the name is set at all times by only having one constructor that takes a std::string as a parameter.
class Tool
{
public:
//Constructor already does the right thing
Tool() = default;
virtual ~Tool();
//Use void or return the modified class, akin to operators
void setName(const std::string& name)
{
m_name = name;
}
//Alternatively
Tool& setName(const std::string &name)
{
m_name = name;
return *this;
}
//Return const reference to the value if possible, avoids copying if not needed
//This will fail at run time if name is not set
//Maybe throw an exception if that is preferred
const std::string& getName() const
{
return *m_name;
//Or
if(m_name) return *m_name;
else throw some_exception;
}
//Or return the optional, then calling code can check if name where set or not
const boost::optional<std::string>& getName() const
{
return m_name;
}
void clearName()
{
m_name = boost::optional<std::string>();
}
private:
boost::optional<std::string> m_name;
};
I wouldn't call that a paradigm. This seems to be a solution for architecture, where a field may be in unspecified state (why not? Sometimes it is a sane requirement). Though, I don't like much this solution, because getter is supposed to return value (symmetrically, setter is supposed to set it) and the convention usually requires specific prototypes:
Type GetValue();
SetValue (const Type & newValue);
or
SetValue (Type & newValue);
or
SetValue (Type newValue);
You shall choose one of three setters depending on situation, usually the first or second one fits.
If a field may be in an unspecified state, I would choose another approach, as M M. suggests in his answer, I'll take liberty to provide an example:
class C
{
private:
int field;
bool fieldSet;
public:
C()
{
field = 0;
fieldSet = false;
}
bool IsFieldSet()
{
return fieldSet;
}
int GetField()
{
if (!fieldSet)
throw std::exception("Attempt to use unset field!");
return field;
}
void SetField(const int newValue)
{
field = newValue;
fieldSet = true;
}
};
Note though, that I wouldn't call this way of implementing getters evil. It may be just uncomfortable to use.
Let's say I have the following:
char cipan[9];
then what should I pass to the function? how about the get and set method??
I'm currently doing like this
set method
void setCipan(char cipan[]){
this->cipan = cipan;
}
and the get method
char getCipan(){
return cipan;
}
and I get an error when compiling??
Im totally blur.. can someone explain what should i pass to the function??
class userData{
private:
string name;
char dateCreate[9];
void userDataInput(string name,char dateCreate[]){
this->name = name;
this->dateCreate = dateCreate;
}
public:
//constructor
userData(string name){
userDataInput(name,dateCreate);
}
userData(string name,char dateCreate[]){
userDataInput(name,dateCreate);
}
//mutator methods
void changeName(string name){this->name = name;}
void changeDateCreate(char *dateCreate){this->dateCreate = dateCreate;}
//accesor methods
string getName(){return name;}
char *getDateCreate(){return dateCreate;}
};
I'd do the following:
void setCipan(const char* new_cipan)
{
strcpy(cipan, new_cipan);
}
const char* getCipan() const
{
return cipan;
}
Of course, the better approach is to use std::string:
void setCipan(const string& new_cipan)
{
cipan = new_cipan;
}
string getCipan() const
{
return cipan;
}
Constructor's purpose is to initialize class variables. I think it's unnecessary to call another method in the constructor to do initialization.
void userDataInput(string name,char dateCreate[]){
this->name = name;
this->dateCreate = dateCreate; // Both the dateCreate are class variables.
}
userData(string name){
userDataInput(name,dateCreate); // dateCreate is already a class variable.
}
dateCreate is the class scope variable. You are just passing it to a method, and re-assigning the same to dateCreate. Assignment operation doesn't copy elements of one array to another and are invalid operations.
To copy array elements, use std::copy instead.