I would like to use a unary function to look up a certain parameter name in a list with std::find
class Parameter {
public:
string getName() { return mName;}
//string mName;
private:
string mName;
string mType;
string mValue;
};
class Param_eq : public unary_function<Parameter, bool> {
string mName;
public:
Param_eq (const string& name) : mName(name) {}
bool operator() (const Parameter& par) const {
return (mName == par.getName());
}
};
double Config::getDouble(string& name) {
list<Parameter>::iterator iParam = find(mParamList.begin(), mParamList.end(), Param_eq(name));
double para = iParam->getDouble();
return para;
}
}
But I get the following compiler error
error C2662: 'Parameter::getName' : cannot convert 'this' pointer from 'const Parameter' to 'Parameter &'
Conversion loses qualifiers
If I make the member variable Parameter::mName public and use it instead of the member function Parameter::getName() in the return statement of Param_eq::operator() it compiles without error.
bool operator() (const Parameter& par) const {
return (mName == par.mName);
}
Why is that? Both member variable and member function are string type.
How do I get the above example to work by using a member function?
The error tells you that you are calling a non-const method on a const reference. A non-const method may modify member variables and thus violate the const constraint.
You can solve this two ways:
Don't call the method at all and access the mName variable directly:
bool operator() (const Parameter& par) const {
return (mName == par.mName);
}
Note that this does not require making mName public. This works because operator() is a member of the Parameter class. Remember that private members are accessible in any method of the class. It does not matter whether you access the private members of another instance of the same class or not.
Declare getName() to be const objects:
string getName() const { return mName;}
Note the location of the const qualifier. This tells the compiler that the method will not modify any member variables.
Related
For a concrete example, say I am given
vector<shared_ptr<DClass>> cVector
and DClass (which is derived from MyClass) has the following interface
class DClass: public MyClass {
public:
DClass( string id, string name, int p, int v )
: MyClass id, name, p ), var1_ ( v ) {}
int GetDClassVar1() const { return var1_; }
private:
int var1_;
};
and MyClass (which DClass inherits from) has the following interface
class MyClass {
public:
MyClass( string id, string name, int p )
: id_( id ), name_( name ), myclassvar1__( p ) {}
string GetMyClassID() const { return id_; }
string GetMyClassName() const { return name_; }
int GetMyClassVar1() const { return myclassvar1__; }
virtual int GetDClassVar1() const { return 0; }
protected:
string id_;
string name_;
int myclassvar1_;
};
How can I call upon the GetDClassVar1 function using cVector assuming that cVector is populated?
***EDIT
I try using
cVector.at(1).GetDClassVar1.()
and I get the error
const value_type’ {aka ‘const class std::shared_ptr<MyClass>’} has no member
named ‘GetDClassVar1'
How can I call upon the GetDClassVar1 function using cVector assuming that cVector is populated
for (const auto& d : cVector)
std::cout << d->GetDClassVar1() << "\n";
Note that when calling a member function that is not const-qualified, you need to remove the const before auto&. For a single element:
cVector.front()->getDClassVar1();
cVector.at(42)->getDClassVar1();
This syntax is due to the fact that std::shared_ptr has an overloaded operator -> member function that forwards to the underlying pointer.
Also note that you want polymorphic base classes to have a virtual destructor, see here.
To access the members of a pointer, you have to use -> instead of .. Other than that, it's pretty much the same!
int result = cVector[0]->GetDClassVar1();
Alternatively, you could dereference it first:
int result = (*cVector[0]).GetDClassVar1();
Or bind it to a reference, if you're doing multiple operations on it:
auto& element = *cVector[0];
int result = element.GetDClassVar1();
Okay so I'm a bit of a noob at C++ and in my second assignment I am required to make classes with public and private arguments etc, etc. Basically the mutator functions won't work because apparently they're not of type const?
This is the header file with the class:
class Customer {
private:
string PhoneNumber_;
string Name_;
string Address_;
public:
string get_PhoneNumber() const {return PhoneNumber_;} // Accessor
const void set_PhoneNumber(unsigned x) {PhoneNumber_ = x;} // Mutator
string get_Name() const {return Name_;}
const void set_Name(unsigned x) {Name_ = x;}
string get_Address() const {return Address_;}
const void set_Address(unsigned x) {Address_ = x;}
};
// declare the CreateCustomer function prototype with default values
Customer* CreateCustomer(const string& id = BLANK, const string& name = BLANK, const string& address = BLANK);
Customer* CreateCustomer(const string& id, const string& name, const string& address) {
Customer* temp = new Customer();
temp->get_PhoneNumber() = id; // Due to the Accessors and Mutators PhoneNumber, Name and Address are now functions
temp->get_Name() = name;
temp->get_Address() = address;
return temp;
}
And this is the error I get in the main.cpp file:
cout << "\n\nDear ";
cout << Charge[0].Holder.set_Name() << " (" << Charge[0].Holder.set_PhoneNumber() << ")"; // DisplayCustomer(customer) ;
cout << ",\n" << Charge[0].Holder.set_Address() << "\n\n"
Basically, the exact error message is:
Member function 'set_Name' not viable: 'this' argument has type 'const
Customer', but function is not type const
It happens with set_PhoneNumber and set_Address as well. Any help would be greatly appreciated! Thanks!
UPDATE: I got it working. Thanks everyone for helping me out!
If you want to set a value, use the set method. get Methods are only to obtain variables, not to set the inner variables of a class (If they are defined the way you did).
The correct usage is:
Customer* CreateCustomer(const string& id, const string& name, const string& address) {
Customer* temp = new Customer();
temp->set_PhoneNumber( id );
temp->set_Name( name );
temp->set_Address( address );
return temp;
}
Also, you have to alter the interface of your methods:
class Customer {
private:
string PhoneNumber_;
string Name_;
string Address_;
public:
string get_PhoneNumber() const {return PhoneNumber_;} // Accessor
void set_PhoneNumber(const string& x) {PhoneNumber_ = x;} // Mutator
string get_Name() const {return Name_;}
void set_Name(const string& x) {Name_ = x;}
string get_Address() const {return Address_;}
void set_Address(const string& x) {Address_ = x;}
};
Since you want to set strings and not numbers.
Using const string& as function arguments is better than string to not copy the string when passing it as an argument. Since it is a const reference, you don't have to fear the function could manipulate the input.
Ehm. I think you should use get and set in reverse way...
In CreateCustomer you should use set functions and when print Customer to stream - you should use get functions.
And set functions should receives string, not unsigned.
And so, it will be better to use constructor, instead of set functions and then will be only get functions.
You should use std:: in the class declaration. See Why is “using namespace std;” considered bad practice? on the question why.
Your set_ methods take unsigned arguments. You cannot assign an unsigned to a string like PhoneNumber_ = x;. The arguments need to be strings.
You'd need to change your members like
std::string get_PhoneNumber() const { return PhoneNumber_; } // Accessor
const void set_PhoneNumber(std::string const & x) { PhoneNumber_ = x; } // Mutator
When you write temp->get_PhoneNumber() = id; your intention is clearly to set the value for PhoneNumber_, so why do you use the get_ method? Just use the appropriate set_ method and write temp->set_PhoneNumber(id);.
Generally avoid pointers in C++. If you're really in need of a pointer use a smart pointer like std::unique_ptr or std::shared_ptr (if and only if you are required to use a plain pointer: use one).
A 'blank' default value for a std::string is an empty string like
std::string const & id = std::string{} Appears clearer to me.
To create an object of type Customer with blank/empty member strings you do not need to do more than Customer customer_object; since there is an implicitly declared default constructor which uses the std::string default constructor which results in an empty strign anyway.
Usually a constructor is used to create an object depending on some arguments values.
You could easily write one that takes all required values and can be used as a default constructo anyway by adding something along the lines of
Customer(const std::string& id = std::string{},
const std::string& name = std::string{},
const std::string& address = std::string{})
: PhoneNumber_(id), Name_(name), Address_(address)
{ }
to your class. See another C++ Class Initialization List example.
See another C++ Class Initialization List example.
For the sake of encapsulation you usually want to avoid using 'direct' getters and setters revealing your data structure.
You've declared PhoneNumber_, Name_ and Address_ as string.
But in the setter methods, you are passing unsigned (int)
Also, you have reversed the usage of getters and setters!
Also, the return types of setters can be just void and not const void.
I tried to use property on c++ to use it instead of too many setter and getter function in data class have lots of member variable.
there are two property class. first one has fixed setter and getter function by default set, get. second one support using custom setter and getter function of its class. below is the code
template <class T>
class Property
{
T data;
public:
// access with function call syntax
Property() : data() { }
T operator()() const
{
return data;
}
T operator()( T const & value)
{
data = value;
return data;
}
// access with get()/set() syntax
T get() const
{
return data;
}
T set( T const & value )
{
data = value;
return data;
}
// access with '=' sign
operator T() const
{
return data;
}
T operator = ( T const & value )
{
data = value;
return data;
}
typedef T value_type; // might be useful for template deductions
};
// a read-write property which invokes user-defined functions
template <class T, class Object, T(Object::*real_getter)(), T(Object::*real_setter)(T const &) >
class RWProperty
{
Object * my_object;
public:
// this function must be called by the containing class, normally in a
// constructor, to initialize the RWProperty so it knows where its
// real implementation code can be found
void operator () ( Object * obj )
{
my_object = obj;
}
// function call syntax
T operator()() const
{
return (my_object->*real_getter)();
}
T operator()( T const & value )
{
return (my_object->*real_setter)( value );
}
// get/set syntax
T get() const
{
return (my_object->*real_getter)();
}
T set( T const & value )
{
return (my_object->*real_setter)( value );
}
// access with '=' sign
operator T() const
{
return (my_object->*real_getter)();
}
T operator = ( T const & value )
{
return (my_object->*real_setter)( value );
}
typedef T value_type; // might be useful for template deductions
};
and i'm testing these properties in OptionSet class before putting it into project code
#include <QString>
class OptionSet
{
public:
explicit OptionSet() {}
Property<QString> m_MeshMode;
RWProperty<uint, OptionSet, &getNumberOfVbo, &setNumberOfVbo> uNumberOfVbo;
// this causes problems
protected:
private:
Property<uint> m_uNumberOfVbo;
uint setNumberOfVbo(const uint& rVboCount)
{
// something to do here
return m_uNumberOfVbo(rVboCount);
}
uint getNumberOfVbo() const
{
return m_uNumberOfVbo();
}
};
but in use RWProperty, even i passed 4 arguments of template like member type, class type has setter and getter function, getter function pointer, setter function pointer in order, it says
"wrong number of template arguments (3, should be 4) :
RWProperty <uint, OptionSet, &getNumberOfVbo, &setNumberOfVbo>
uNumberOfVbo"
"provided for 'template<class T, class Object,
T(Object::*real_getter)(), T(Object::*real_setter)(const T&)> class
RWProperty : class RWProperty"
I guess i'm doing something wrong to pass arguments in template.
is there anyone knows what happened?
There are three mistakes in your code:
Firstly, to get the address of a member function, you need to include the class name:
RWProperty<uint, OptionSet
, &OptionSet::getNumberOfVbo
// ~~~~~~~~~~~^
, &OptionSet::setNumberOfVbo> uNumberOfVbo;
// ~~~~~~~~~~~^
Secondly, to form a pointer to const qualified member function, you need to append const keyword to the declaration of that pointer:
T (Object::*real_getter)() const
// ~~~~^ to match 'uint getNumberOfVbo() const'
Lastly, OptionSet inside OptionSet itself is an incomplete type. You can't refer to its member unless the point of declaration of that member comes first. This basically means you need to reorder your declarations within OptionSet so that setNumberOfVbo and getNumberOfVbo comes before you declare uNumberOfVbo data member:
class OptionSet
{
//...
uint setNumberOfVbo(const uint& rVboCount) { /*...*/ }
uint getNumberOfVbo() const { /*...*/ }
// Ok, now they are known and can be found in the class scope
//...
RWProperty<uint, OptionSet
, &OptionSet::getNumberOfVbo
, &OptionSet::setNumberOfVbo> uNumberOfVbo;
};
I want to a member variable, which is a double pointer. The object, the double pointer points to shall not be modified from outside the class.
My following try yields an
"invalid conversion from ‘std::string**’ to ‘const std::string**’"
class C{
public:
const std::string **getPrivate(){
return myPrivate;
}
private:
std::string **myPrivate;
};
Why is the same construct valid if i use just a simple pointer std::string *myPrivate
What can i do to return a read-only double pointer?
Is it good style to do an explicit cast return (const std::string**) myPrivate?
Try this:
const std::string * const *getPrivate(){
return myPrivate;
}
The trouble with const std::string ** is that it allows the caller to modify one of the pointers, which isn't declared as const. This makes both the pointer and the string class itself const.
If you want to be really picky :
class C {
public:
std::string const* const* const getPrivate(){
return myPrivate;
}
private:
std::string **myPrivate;
};
There are very rare cases in c++ when a raw pointer (even less for a double pointer) is really needed, and your case doesn't seams to be one of them. A proper way would be to return a value or a reference, like this :
class C{
public:
const std::string& getPrivate() const
{
return myPrivate;
}
private:
std::string myPrivate;
};
For some tracing automation for identifying instances i want to call either:
a non-static method of the containing object returning its identifier
something else which always returns the same id
My current solution is to have a base class with a method which() and a global function which() which should be used if not in the context of an object.
This however does not work for static member functions, here the compiler prefers the non-static method over the global one.
Simplified example:
class IdentBase
{
public:
Ident(const std::string& id) _id(id) {}
const std::string& which() const { return _id; }
private:
const std::string _id;
};
const std::string& which() { static const std::string s("bar"); return s; }
#define ident() std::cout << which() << std::endl
class Identifiable : public IdentBase
{
public:
Identifiable() : Ident("foo") {}
void works() { ident(); }
static void doesnt_work() { ident(); } // problem here
};
Can i somehow avoid using work-arounds like a special macro for static member functions (maybe using some template magic)?
Define a function template that returns a default identifier for all types.
template<typename T>
const std::string& which(const T& object)
{ static const std::string s("bar"); return s; }
Specialize the function template for the specific class.
class IdentBase
{
public:
IdentBase(const std::string& id): _id(id) {}
const std::string& id() const { return _id; }
private:
const std::string _id;
};
template<>
const std::string& which(const IdentBase& object)
{ return object.id(); }
Call the function template by passing an instance that you want to identify.
int main()
{
int i;
std::cout << which(i) << std::endl;
IdentBase foo("foo");
std::cout << which(foo) << std::endl;
return 0;
}
You might be able to to use is_member_function_pointer from the Boost TypeTraits library. sbi's suggestion of using different code in the static and non-static cases is probably better though.
Do you need a different identifier for every instance of each class as in your example, or are you just trying to identify which class is in the trace?
Changing your which() function and _id member to static would expose them both to your static member functions, and as a bonus decrease your memory usage.