In my Class i have a boolean variable
class Sum_SystemTagControlVisitor : public FunctionVisitor
{
private:
std::string variableName;
std::string variableValue;
std::string variableValue1;
bool m_bIsTimer{ false };
public:
Sum_SystemTagControlVisitor(std::string varName, std::string varValue ) : variableName(varName), variableValue(varValue) { }
Sum_SystemTagControlVisitor(std::string varName, std::string varValue , bool isTimer) : variableName(varName), variableValue(varValue) , m_bIsTimer(isTimer){ }
Sum_SystemTagControlVisitor(std::string varName, std::string varValue, std::string varValue1) : variableName(varName), variableValue(varValue), variableValue1(varValue1) { }
virtual void visit(Sum_TagControl& tagControl ) override;
};
Only one of the constructor is able to set the boolean value and for the other two constructors will it be always be false ?
Inline initialization of member variables will always take place, unless your initializer list contains an entry for that variable.
So in short: For the constructor that doesn't initialize the variable, it will be automatically initialized to false.
Related
I'm a newbie in developing with C++.
I get an error in "this->Buchtitel = buchtitel;" and can't understand why. I have to use const when initializing the variables in Book.h. The Error-Code is: E0349
Book.h
std::string const Buchtitel;
std::string const Autor;
std::string const Anschaffungsdatum;
bool const Status;
Book.cpp
void Book::setBuchtitel(std::string buchtitel) {
this->Buchtitel = buchtitel;
}
void Book::setAutor(std::string autor) {
this->Autor = autor;
}
void Book::setAnschaffungsdatum(std::string anschaffungsdatum) {
this->Anschaffungsdatum = anschaffungsdatum;
}
void Book::setStatus(bool status) {
this->Status = status;
}
How should "setBuchtitel" be written so it doesn't throw an error?
The value of a const variable can only be set during initialization of the variable. For a member variable that's as a default member initializer
std::string const Buchtitel = "Das Boot";
or in the constructor's member initializer list
book(string titel): Buchtitel{titel}
{
}
The value cannot be set anywhere else. In this case the default member initializer is next to useless to you because if it is used exclusively, all books will have the same title.
This makes writing a setter for a const member variable impossible.
I am trying to implement something similar to C# setters in C++. The idea is to have an enum of class properties and the corresponding setters. My code looks as follows. I will write the implementation in the class definition.
#include <string>
#include <map>
enum ClassProperties
{
Id, Name
};
class MyClass
{
public:
int Id;
std::string Name;
public void SetValue(ClassProperties c, std::string value){
setters[c](this, value);
}
private:
typedef void (* t_setter)(MyClass *, std::string);
static void set_id(MyClass * obj, std::string value) {
obj->Id = std::stoi(value);
}
static void set_name(MyClass * obj, std::string value) {
obj->Name = value;
}
static std::map<ClassProperties, t_setter> setters = {{ClassProperties:: Id, set_id}, {ClassProperties::Name, set_name}};
};
I'd expect this code to choose the cooresponding function and call it, but I get an error on the last line
error: in-class initialization of static data member ‘std::map<ClassProperties, void (**)(MyClass*, std::basic_string<char>)> MyClass::setters’ of incomplete type
error: could not convert ‘{{Id, MyClass::set_id}, {Name, MyClass::set_name}}’ from ‘<brace-enclosed initializer list>’ to ‘std::map<ClassProperties, void (**)(MyClass*, std::basic_string<char>)>’
What am I doing wrong?
Your initialization of setters is wrong. You should change it as follows:
1) Remove the line from the class body:
static std::map<ClassProperties, t_setter> setters =
{{ClassProperties:: Id, set_id}, {ClassProperties::Name, set_name}};
2) Add appropriate initialization of static member out of the class body:
std::map<ClassProperties, MyClass::t_setter> MyClass::setters = {
{ ClassProperties::Id, &MyClass::set_id },
{ ClassProperties::Name, &MyClass::set_name }
};
Besides, you have to remove public specifier before SetValue function.
wandbox example
const fields in C++ must be initialized in the initialization list, this makes non trivial the computation of interdependent values from the constructor parameters.
What is(are) the best way(s) to translate, for example, this piece of java code into c++ ?
public class SomeObject {
private final String some_string;
private final int some_int;
public SomeObject(final String input_filename){
SomeReader reader(input_filename);
some_string = reader.getString();
some_int = reader.getInt();
reader.close();
}
}
I thought of encapsulating a sub-object in SomeObject, but this is just shifting the problem; or constructing the object using a static method:
class SomeObject {
private:
const std::string some_string;
const int some_int;
public:
static SomeObject unserialize(const char * input_filename){
SomeReader reader = new SomeReader(input_filename);
string str = reader.get_string();
int i = reader.get_int();
reader.close();
SomeObject obj(str, i);
return obj;
};
SomeObject(const std::string str, const int i) :
some_string(str),
some_int(i)
{};
}
Is there a better solution ?
Thank you.
This is a great application for C++11 constructor delegation:
class SomeObject {
private:
const std::string some_string;
const int some_int;
public:
// The "real" constructor for SomeObject
SomeObject(std::string str, const int i) :
some_string{std::move(str)},
some_int{i}
{}
// Deserialize from SomeReader (delegates to the primary constructor)
SomeObject(SomeReader& reader) :
SomeObject{reader.get_string(), reader.get_int()} {}
// Deserialize from SomeReader (accepts rvalues,
// delegates to the lvalue constructor)
SomeObject(SomeReader&& reader) :
SomeObject{reader} {}
// Deserialize from named file (delegates to the SomeReader&& constructor)
SomeObject(const char* input_filename) :
SomeObject{SomeReader{input_filename}} {}
};
You can use a delegating ctor and a lambda-function, like this:
SomeObject(const char* filename) : SomeObject([&]{
/* Do calculations here */
return std::make_tuple(...);
}()) {}
SomeObject(std::tuple<...>&& x) : /* ... */ {}
Still, a much better idea is probably a re-design to make use of all the things you can do in C++ and cannot do in Java.
I think you have the right approach.
I would recommend couple of minor changes.
This is not correct C++.
SomeReader reader = new SomeReader(input_filename);
Perhaps you meant:
SomeReader reader(input_filename);
You can change the lines:
SomeObject obj(str, i);
return obj;
to
return SomeObject(str, i);
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 have an object, every member variable in this object has a name which I can acquire it by calling get_name() ,what I want to do is concatenate all the names of the member variables in alphabetical order, then do something. for example:
class CXMLWrapper<class T>
{
public:
CXMLWrapper(const char* p_name) : m_local_name(p_name)
{
}
//skip the get_name(), set_name() and others
private:
string m_local_name;
T m_type_var;
}
class object
{
public:
object() : m_team("team"), m_base("base")
{
}
public:
CXMLWrapper<string> m_team;
CXMLWrapper<string> m_base;
...
}
I have to hard-code like this:
object o;
string sign = o.m_base.get_name();
sign += o.m_team.get_name();
I need a function to do this instead of copying and pasting when the object varies. Anyone has an idea?
One way to do this in normal C++, provided all of the members belong to the same class or are derived from some base class will be to use variable number of arguments to a function. An example follows.
#include <stdarg.h>
string concatenateNames(int numMembers, ...)
{
string output;
va_list args;
va_start(args, numMembers);
for(int i = 0; i < numMembers; i++)
{
MemberClass *pMember = va_arg(args, MemberClass*);
output += pMember->get_name();
}
va_end(args);
return output;
}
class Object
{
public:
MemberClass x;
MemberClass y;
MemberClass z;
};
int main()
{
Object o;
string sign = concatenateNames(3, &o.x, &o.y, &o.z);
}
If the types of all the members are different, you can look into variadic templates of C++11x: http://en.wikipedia.org/wiki/Variadic_Templates, but I can't seem to find a way to do otherwise.
If variables which have name have a same type (or these types belongs one hierarchy) you can use map of these vars. Is not good way, but maybe it helps you
Example
class object
{
public:
object() //: m_team("team"), m_base("base")
{
this->vars["m_team"] = CXMLWrapper<string>("team");
//.....
}
public:
map<string, CXMLWrapper<string> > vars;
/*CXMLWrapper<string> m_team;
CXMLWrapper<string> m_base;*/
...
}
object o;
string sign;
for(auto& x : o.vars)//i cannot remember syntax of for of map
sign += x.get_name;
PS Sorry for my writing mistakes. English in not my native language.
One method is to have an external library of member names which the CXMLWrapper class updates:-
class BaseXMLWrapper
{
public:
void ListMembers (const char *parent)
{
// find "parent" in m_types
// if found, output members of vector
// else output "type not found"
}
protected:
void RegisterInstance (const char *parent, const char *member)
{
// find 'parent' in m_types
// if not found, create a new vector and add it to m_types
// find 'member' in parent vector
// if not found, add it
}
private:
static std::map <const std::string, std::vector <const std::string> >
m_types;
};
class CXMLWrapper <class T, const char *parent> : BaseXMLWrapper
{
public:
CXMLWrapper(const char* p_name) : m_local_name(p_name)
{
RegisterInstance (parent, p_name);
}
// you could override assignments, copy and move constructors to not call RegisterInstance
//skip the get_name() set_name()
private:
m_local_name;
}
class object
{
public:
object() : m_team("team"), m_base("base")
{
}
public:
CXMLWrapper<string, "object"> m_team;
CXMLWrapper<string, "object"> m_base;
...
};
This does add overhead to the construction of objects, but as it's only a constructor overhead it might not affect overall system performance much.
This looks like a "observe pattern", you just need to keep a single copy in object as a member variable "string name_;", and pass the name_s's reference into CXMLWrapper like this:
class CXMLWrapper<class T>
{
public:
CXMLWrapper(const string &name)
: local_name_(name)
{
}
//skip the get_name() set_name()
private:
const string &local_name_;
}
class object
{
public:
object()
: team_("team"),
base_("base"),
m_team(team_)
, m_base(base_)
{
}
public:
string team_;
string base_;
CXMLWrapper<string> m_team;
CXMLWrapper<string> m_base;
}