so I have a class Data which has a multiset container and I have a class Item which has "erscheidatum" as one of the constructor parameters,so I want this parameter escheidatum to be inserted in the multiset in the data class i tried to do that in the constructor of the Item class but when I am printing the set its empty the console is empty,i dont know if its possible to insert a set from another class.
//this is Item.h file
#include"Data.h"
#include<string>
class Item
{
public:
Item(std::string Name,int erschDatum, Data pd)// i put Data variable here though that i dont need it just to get access to->
:_Name(Name), dataobject(pd), _erda(erschDatum)//->data class maybe its not the best way.
{
dataobject.insert(erschDatum);
}
~Item();
private:
Data dataobject;
std::string _Name;
int _erda;
};
and this is my Data.h file
#include<set>
#include<iostream>
class Data
{
public:
Data();
std::multiset<int>dataset;
void insert(int a) {
dataset.insert(a);
}
void showData() {
for (const auto& e : dataset) {
std::cout << e << std::endl;
}
}
~Data();
};
and this the main function
#include<iostream>
#include"Item.h"
#include"Data.h"
int main(){
Data DaOb;
Item Buch("xy", 1996,DaOb);
DaOb.showData();
}
You should use reference of Data as parameter of Item. Like this
class Item
{
public:
Item(std::string Name,int erschDatum, Data& pd)// i put Data variable here though that i dont need it just to get access to->
:dataobject(pd), _Name(Name), _erda(erschDatum)//->data class maybe its not the best way.
{
dataobject.insert(erschDatum);
}
~Item();
private:
Data& dataobject;
std::string _Name;
int _erda;
};
Related
Im new to C++ and I am curious to know if you can create multiple constructors with the same arguments. Say for example I have this class in which I have patients and I have their name and their age. I know I can create a constructor like this:
class hospital {
hospital(){
setname("John");
setage(24);
}
private:
string name;
int age;
};
but could I create another constructor just like I did above. Something like:
hospital patientBilly(){
setname("Billy");
setage(32);
}
The problem is that you redefine the constructor. Allowed is only one definition.
Simplified example:
void myFunc (){};
void myFunc (){};
int
main ()
{
myFunc ();
}
I whould make the Hospital class like this:
#include <string>
struct Hospital // struct here to signal we have no invariant. you could also use a class and make the member public
{
std::string name{}; // no setter and getter if you do not have invariant.
int age{};
};
int
main ()
{
auto hospital = Hospital{ .name = "John", .age = 42 }; //c++20 Designated Initializers so we can construct Hospital with a name and age without defining a constructor
}
I believe you are currently only a bit confused. So lets become the things sorted...
A class describes how objects should behave. The constructor is part of that description and equal to all the instances it will later on create. Your first step for understanding should be: There is a single class and multiple instances/objects of it.
So you write a single class and give for each of the instances/objects different parameters to get different objects.
Example:
class hospital {
public:
hospital(const std::string& name_, int age_ ):
name { name_ }, age{ age_ }{
}
void Print() const
{
std::cout << "Hospital" << name << ":" << age << std::endl;
}
private:
std::string name;
int age;
};
int main()
{
hospital hospital1{ "John", 24 };
hospital hospital2{ "Bill", 77 };
hospital1.Print();
hospital2.Print();
}
You can also create a different class for every of your later created objects, but I believe that is never what you want to do, especially not at the beginning of your C++ career!
If you want to create some kind of list of instances, you can store the objects in containers and act on the containers as you like.
int main()
{
std::vector< hospital > objs;
objs.emplace_back( "John", 24 );
objs.emplace_back( "Bill", 77 );
for ( const auto& hos: objs )
{
hos.Print();
}
}
In your problem you have two concepts, which you are trying to mix.
hospitals and patients. So it makes sense to model them as two distinct classes.
This way you can model a patient as something that has an age and a name.
And a hospital as something that "contains" patients.
Give the patient a contructor where you can pass age and name.
And give the hospital a method or methods to add patients.
In the example I show to variants of how you could add patients to a hospital.
I also have use unsigned variable types for numbers that can never be smaller then 0. And I use the const keyword a lot for places in the code where values must only be used, and should not be changed.
#include <iostream>
#include <string>
#include <utility>
#include <vector>
//---------------------------------------------------------------------------------------------------------------------
class patient_t
{
public:
// You need a constructor like this
patient_t(const unsigned int age, const std::string& name ) :
m_age{ age },
m_name{ name }
{
}
// getter function for observing private data
const unsigned int& age() const noexcept
{
return m_age;
}
// getter function for observing private data
const std::string& name() const noexcept
{
return m_name;
}
private:
unsigned int m_age;
std::string m_name;
};
// a useful output function to have (will make code later shorter)
std::ostream& operator<<(std::ostream& os, const patient_t& patient)
{
os << "Patient : " << patient.name() << ", age : " << patient.age() << std::endl;
return os;
}
//---------------------------------------------------------------------------------------------------------------------
class hospital_t
{
public:
void add_patient(const unsigned int age, const std::string& name)
{
m_patients.emplace_back(age,name); // will call patient constructor with two parameters age and name and puts it into vector
}
void add_patient(const patient_t& patient)
{
m_patients.push_back(patient); // store a copy of patient in the vector
}
const auto& patients() const
{
return m_patients;
}
private:
std::vector<patient_t> m_patients;
};
//---------------------------------------------------------------------------------------------------------------------
int main()
{
hospital_t hospital;
patient_t billy{ 42, "Billy" };
hospital.add_patient(billy);
hospital.add_patient(31, "Jane");
for (const auto& patient : hospital.patients())
{
std::cout << patient;
}
}
If I have understood correctly then what you need is to define two constructors
hospital( const std::string &name, int age )
{
setname( name );
setage( age );
}
hospital() : hospital( "John", 24 )
{
}
Then you will can write declaring an object of the class
hospital patientBilly( "Billy", 32 );
suppose i have a simple C++ class :
class Calc
{
private:
int a;
public:
Calc(){
a = 0;
}
void seta(int a){
this->a = a;
}
int geta(){
return a;
}
};
Now, suppose, in main i create a object of this class, and take two inputs from user : var_name which is name of instance variable in string format, and action which is set or get in string format. For ex : if var_name = "a" and action == "get" , then i should be able to call geta() fn. Is there any way to achieve this in C++.
pls dont provide if..then..else kind of soln. I want to write a generic code which need not be updated as more members are added in class Calc.
You cannot dynamically modify C++ types. However, it sounds like you just want a way to set and read attributes. You don't need to modify your class structure for this, there are other alternative solutions. For example you could use an std::map:
class Calc
{
private:
std::map<std::string, int> attributes;
public:
Calc(){}
void setAttr(const std::string& name, int value){
attributes[name] = value;
}
int getAttr(const std::string& name){
return attributes[name];
}
};
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;
}
So, I have got the following classes and methods:
Property: Has a single member of type int (named mTag)
TypedProperty: Inherits from the Property class and adds a member called mValue of type T to it.
PropertyList: A class which Maintains a std::set of Property and has an Add and Print method.
CheckSubset: A method which checks if a std::set is included in another set.
I don't know how I should implement the CheckSubset method. Because I do not know how to iterate through a set<Property> and access to the template member (mValue). I also tried to use the includes method, which did not work (even if it worked, I would have no idea how it did!). The same problem exists in the PropertyList::Print method, where I do not know what cast should be used.
Any advice on the implementation of CheckSubset and Print methods would be appreciated!
Updated source code (using pointer)
#include <string>
#include <iostream>
#include <set>
#include <algorithm>
#include <tr1/memory>
using namespace std;
/////////////////// Property Class //////////////////////
class Property
{
public:
Property(){};
Property(const int tag)
: mTag(tag) {}
virtual ~Property() {}
int mTag;
bool operator<(const Property &property) const
{
return mTag < property.mTag;
}
};
/////////////////// TypedProperty Class /////////////////
template< typename T >
class TypedProperty : public Property
{
public:
TypedProperty (const int tag, const T& value)
: Property(tag), mValue(value){}
T mValue;
};
/////////////////////////////////////////////////////////
typedef std::tr1::shared_ptr<Property> PropertyPtr;
/////////////////// PropertyList Class /////////////////
class PropertyList
{
public:
PropertyList(){};
virtual ~PropertyList(){};
template <class T>
void Add(int tag, T value)
{
PropertyPtr ptr(new TypedProperty<T>(tag, value));
mProperties.insert(ptr);
}
void Print()
{
for(set<PropertyPtr>::iterator itr = mProperties.begin(); itr != mProperties.end(); itr++)
{
cout << ((PropertyPtr)*itr)->mTag << endl;
// What should I do to print mValue? I do not know its type
// what should *itr be cast to?
}
}
set<PropertyPtr> mProperties;
};
//////////////////// Check Subset ///////////////////////
/*
* Checks if subset is included in superset
*/
bool CheckSubset(set<PropertyPtr> &superset, set<PropertyPtr> &subset)
{
// How can I iterate over superset and subset values while I do not know
// the type of mValue inside each Property?
// I also tried the following method which does not seem to work correctly
return includes(superset.begin(), superset.end(),
subset.begin(), subset.end());
}
int main()
{
PropertyList properties1;
properties1.Add(1, "hello");
properties1.Add(2, 12);
properties1.Add(3, 34);
properties1.Add(4, "bye");
properties1.Print();
PropertyList properties2;
properties2.Add(1, "hello");
properties2.Add(3, 34);
if(CheckSubset(properties1.mProperties, properties2.mProperties)) // should be true
cout << "properties2 is subset!" << endl;
PropertyList properties3;
properties3.Add(1, "hello");
properties3.Add(4, 1234);
if(CheckSubset(properties1.mProperties, properties3.mProperties)) // should be false
cout << "properties3 is subset!" << endl;
}
What you want, cannot be done with the current design.
Your approach fails with std::set<Property>.
std::set<Property> will slice. That means that it will only copy the Property part and forget to copy the additional TypedProperty<T> members.
As a result, inside PropertyList::print(), there is no way to access the mValue.
If you want to store TypedProperty<T>s inside a std::set, you must use some sort of pointer. I.e. either std::set<Property*>, or a smart pointer version.
For solving the problem in Print method of PropertyList, you could write a Print method for TypedProperty class, which prints its tag and value.
But about the problem in accessing mValue which you want to do some operations on, I can't think of a way using normal types and templates to get the mValue without engaging your parent class Property with template type of TypedProperty (which seems undesirable). But you could get the address of mValue and cast it to void* to eliminate the type problem. This way you will face another problem, that you can not point to value of a void* pointer, so you can not work with your pointer in parent level. Therefore, you should write a method (implemented by TypedProperty) that takes a void* pointer and casts it to the type defined in child and perform the desired operation.
For example in the following code, I assumed you want to check equality of a value in a TypedProperty with another one of the same type (IsEqual method).
Now you can implement simply CheckSubset using IsEqual (checking two elements would be like: superItr->IsEqual(subItr->GetValue())).
class Property
{
public:
Property(){};
Property(const int tag)
: mTag(tag) {}
virtual ~Property() {}
virtual void* GetValue() = 0;
virtual bool IsEqual(void* value) = 0;
virtual void Print() = 0;
int mTag;
bool operator<(const Property &property) const
{
return mTag < property.mTag;
}
};
template< typename T >
class TypedProperty : public Property
{
public:
TypedProperty (const int tag, const T& value)
: Property(tag), mValue(value){}
void* GetValue()
{
return &mValue;
}
bool IsEqual(void* value)
{
return *((T*)value) == mValue;
}
void Print()
{
cout << "Tag: " << mTag << ", Value: " << mValue << endl;
}
T mValue;
};
typedef std::tr1::shared_ptr<Property> PropertyPtr;
class PropertyList
{
public:
PropertyList(){};
virtual ~PropertyList(){};
template <class T>
void Add(int tag, T value)
{
PropertyPtr ptr(new TypedProperty<T>(tag, value));
mProperties.insert(ptr);
}
void Print()
{
cout << "-----------" << endl;
for(set<PropertyPtr>::iterator itr = mProperties.begin(); itr != mProperties.end(); itr++)
{
(*itr)->Print();
}
}
set<PropertyPtr> mProperties;
};