Accessor functions by data member assignment - c++

I want to enhance members of C++ classes so that assignment from/to them results in the call of a custom getter/setter.
Like
class Class
{
public:
int Member;
void SetMember(int Value); // TBD
int GetMember(); // TBD
}
and
Class Instance;
Instance.Member= 3; // Causes a call to SetMember(3);
int Data= Instance.Member; // Causes a call to GetMember();
I have found a way to force a function call upon member assignment, by turning the member type to a class holding a private value, and overloading the cast operator for reading and the assignment operator for writing.
class WrapInt
{
public:
operator int() const { return Value; }
void operator=(const int Assign) { Value= Assign; }
private:
int Value;
}
This works, but in a generic way, I cannot customize the getters/setters per member but only per data type.
Do you see a way to refine so that I can write different accessors for different members of the same type ?
Update:
I have now found a solution that satisfies my needs. The members that require a special setter are defined using a class that knows the hosting class:
template<class Parent> class WrapInt
{
public:
int operator=(const int Value) { (This->*Setter)(Value); return Value; }
operator int() { return Value; }
private:
int Value;
Parent* This;
void (Parent::*Setter)(int Value);
friend Parent;
};
Assigning such a member invokes the assignment operator, which calls a plain setter function via a pointer to method of the main class. The Get operation is implemented via the cast operator, which just returns the member value (the scheme might be enhanced to support custom getters, but I didn't need that).
This is pretty costly as every member takes an extra This pointer to the class instance and a pointer to the setter; these need to be initialized in the class constructor (if not, a crash is guaranteed).
So this takes some effort on the side of the class writer (initialization in the constructor), but then assigning to the member automatically invokes the setter, as I want.
class Class
{
public:
Class();
WrapInt<Class> Member;
private:
void SetMember(int Value); // TBD
}
Class::Class() { Member.This= this; Member.Setter= &Class::SetMember; }
On the side of the user,
Class Instance;
Instance.Member= 3; // Calls the setter SetMember
cout << Instance.Member;
that's it.

You could make your class WrapInt modifyable.
Option 1: At runtime, using a function object
class WrapInt
{
public:
operator int() const { return Value; }
void operator=(const int Assign)
{
assign_callback(Assign);
Value = Assign;
}
private:
int Value;
std::function<void (int)> assign_callback;
}
In this variant, you would have to assign the correct callbacks in the constructor of the containing class:
class Container
{
WrapInt a, b, c;
Container ()
{
a.assign_callback = ...;
b.assign_callback = ...;
c.assign_callback = ...;
}
}
Option 2: At compile-time, using inheritance
class WrapInt
{
public:
operator int() const { return Value; }
void operator=(const int Assign)
{
assign_callback(Assign);
Value = Assign;
}
private:
int Value;
virtual void assign_callback(int) = 0;
}
In this variant, you would inherit from WrapInt multiple times in the class body of the containing class
class Container
{
class WrapIntA : public WrapInt {
void assign_callback() { ... };
} a;
class WrapIntB : public WrapInt {
void assign_callback() { ... };
} b;
class WrapIntC : public WrapInt {
void assign_callback() { ... };
} c;
}

A modified version of your code:
class WrapInt
{
public:
WrapInt(std::function<int()> getter, std::function<void(int)> setter) :
getter(getter),
setter(setter)
{}
WrapInt(const WrapInt&) = delete;
WrapInt& operator =(const WrapInt&) = delete;
operator int() const { return getter(); }
void operator=(int value) { setter(value); }
private:
std::function<int()> getter;
std::function<void(int)> setter;
};
class Class
{
public:
Class() : Member([this](){ return this->GetMember();},
[this](int value) {SetMember(value); })
{}
WrapInt Member;
void SetMember(int Value); // TBD
int GetMember(); // TBD
};

Don't fight the language: C++ does not support get / set bindings to functions. You merely have to tolerate
Instance.Member() = 3;
and
int Data = Instance.Member();
Which you can provide by supplying a const function Member() that returns a const reference, and a non-const version that returns a non-const reference.
One criticism of C++ is the amount of boilerplate you need to write, especially if you need this for every member variable in your class. But really at that point, you are pretty much circumventing encapsulation entirely: you may as well make the members public unless your functions make consistency checks.

Related

Can inhereted classes be made const? [duplicate]

I would like to inherit from a class with the const specifier like this:
class Property
{
int get() const;
void set(int a);
};
class ConstChild : public const Property
{
// Can never call A::set() with this class, even if
// the instantiation of this class is not const
};
class NonConstChild : public Property
{
// Can call both A::set() and A::get() depending on
// the constness of instantiation of this class
};
My compiler obviously gives me an error for the const keyword in the second classes declaration. Ideally I'd like to avoid having to create a new class ReadOnlyProperty from which ConstChild would inherit.
Can I somehow use the const keyword for inheritance?
If not, do you have any other ideas on how to solve this problem?
Introduce mutability later in your inheritance tree and derive appropriately:
class Property
{
int get() const;
};
class MutableProperty : public Property {
{
void set(int a);
};
And then:
class ConstChild : public Property { ... };
class MutableChild : public MutableProperty { ... };
I had the need for a related problem, which is: to really control/highlight mutable and const access on some class.
I did it with this simple reusable template wrapper:
template <typename T>
class TAccessor : private T
{
public:
const T& Const() const { return *this; }
T& Mutable() { return *this; }
};
// Example of use:
template <typename T>
using MyVector = TAccessor<std::vector<T>>;
void main()
{
MyVector<int> vector;
vector.Mutable().push_back(10);
int x = vector.Const()[1];
...
}
If you create a const member function set, you will get what you need.
class Property
{
int get() const;
void set(int a);
};
class ConstChild : public Property
{
void set(int a) const {}
};
The only caveat is that a sly user can circumvent your intention by using:
ConstChild child;
child.set(10); // Not OK by the compiler
Property& base = child;
base.set(10); // OK by the compiler
I would like to inherit from a class with the const specifier"
However much you want to is irrelevant. You cannot. That is not valid C++.
Can I somehow use the const keyword for inheritance?"
No.
Use a data member or private base class instead of public base class.
Then you control the access to that member.
You can make the Property thing an abstract interface if you need polymorphic behavior.
You can use a template class and a specialization for a constant type:
template<typename T> class base_property {
protected:
T value;
};
template<typename T> class property : public base_property<T> {
public:
const T& get()const { return value; }
void set(const T& v){ value = v; }
};
template<typename T> class property<const T> : public base_property<T> {
public:
const T& get()const { return value; }
};
class ConstChild : public property<const int>{ };
I had the same need and I ended up with this quite manual approach :
class A
{
public:
void fooMutable(void) {}
void fooConst(void) const {}
};
class B : private A
{
public:
using A::fooConst;
const A& getParent(void) const
{
return *this;
}
};
void fooParent(const A&) {}
int main(void)
{
auto b = B{};
b.fooConst(); // Ok
b.fooMutable(); // Fail
fooParent(b); // Fail
fooParent(b.getParent()); // Ok
return 0;
}
Note that the using keyword would not work with overloads const/mutable :
class A
{
public:
void foo(void) {}
void foo(void) const {}
};
class B : private A
{
public:
using A::foo; // Expose the const and the mutable version
};
To solve this you could redefine the function yourself and call the parent :
class B : private A
{
public:
void foo(void) const
{
A::foo();
}
};
It can become pretty time consuming if you're inheriting a large hierarchy, but if it's for a not-so-big class it should be very reasonable and being quite natural for the user.
I have a trick, not a clean solution.
class ConstChild : private Property
{
operator const Property () { return *this; }
};
then
ConstChild cc;
cc.set(10); // ERROR
cc().get();

How I set a reference after constructor?

I want to set a reference after constructor
Example:
class OtherClass
{
public:
OtherClass() : m_class(Class()){}
inline void SetData(int data1, int data2)
{
//calculate data3
// I tried:
m_class = Class(data3);
//but it doesn't worked
}
protected:
private:
Class& m_class;
};
Edit:
The Exception is: vector subscript out of range
because I have glm vectors in the Class.
I need also call functions in my Class.
Edit 2:
Why I need this?
Because I have an other class [ExClass] which extends and which have to calulate in constructor:
ExClass::ExClass(float d1, float d2, ...) {
//calculate data from given values
SetData(data);
}
The proper way to do that is to use a pointer and not a reference, as opposed to references - pointers can be set after object creation. Note also that referring (or pointing) to a local variable whose lifetime will end, while still in use, is a bad idea.
Your code may be changed to use a pointer and dynamic allocation or alternatively, std::unique_ptr. There are of course other options, these are just examples.
Option 1 - a pointer and dynamic allocation
class OtherClass
{
public:
OtherClass() : m_class(nullptr){}
~OtherClass() {
delete m_class;
}
// block copy and assignment (or implement them)
OtherClass(const OtherClass&) = delete;
OtherClass& operator=(const OtherClass&) = delete;
void setData(int data1, int data2)
{
// ... calculate data3 ...
m_class = new Class(data3);
}
bool hasInnerObj() const {
return m_class; // or: return m_class != nullptr;
}
/** call this function only if hasInnerObj() returned true */
Class& getInnerObj() {
return *m_class;
}
private:
Class* m_class;
};
Option 2 - std::unique_ptr
class OtherClass
{
public:
void setData(int data1, int data2)
{
// ... calculate data3 ...
m_class = std::make_unique<Class>(data3);
}
bool hasInnerObj() const {
return m_class; // or: return m_class != nullptr;
}
/** call this function only if hasInnerObj() returned true */
Class& getInnerObj() {
return *m_class;
}
private:
std::unique_ptr<Class> m_class;
};
You have two problems:
Reference class members (i.e. m_class) need to be initialized when object is created.
However, both your Class instances (one in the constructor, and one in SetData) are put on the stack and popped right away, making the reference invalid.
What you need to do is make sure that your class object actually lives through the function call. One way of achieving that is allocating it prior to passing it to the OtherClass constructor or SetData function:
class Class {};
class OtherClass
{
public:
OtherClass(Class& c) : m_class(c){}
inline void SetData(Class& c)
{
m_class = c;
}
protected:
private:
Class& m_class;
};
int main()
{
Class a;
OtherClass c(a);
Class b;
c.SetData(b); // changes m_class
return 0;
}
Live example here.

How to make inaccessible class variable

I'm wondering if it is possible to make a class variable inaccessible inside this class? The only way to change the value of this variable will be through class setter. For example:
class foo
{
private:
int m_var;
bool m_isBig;
void setVar(int a_var)
{
// do something before setting value, like emitting signal
m_var = a_var;
}
void method()
{
int copy = m_var; // ok
m_var = 5; // error!
setVar(101); // ok
doSomething();
}
void doSomething()
{
if(m_var > 5)
{ m_isBig = true; }
else
{ m_isBig = false; }
}
};
I know that I could write another class only with setters and getter, but then I will don't have access to other methods/vars from class foo(encapsulation!). I think this could be a common problem, and there could be some design pattern for this, but I can't found any.
EDIT:
I edited the code to be clear, what I want to do in setter.
I'm not aware of a pattern for this, but one possibility is to wrap the member inside a nested class. I think this is also better style, since the creation of a new type expresses the intent that this member is not just an integer, but, instead, has unique behaviour.
class foo {
class MVar {
public:
MVar(foo* parent, int value = 0) : m_parent(parent), m_value(value) {}
MVar& operator=(const MVar&) = delete; // disable assignment
operator int() const { return m_var; }
void set(int new_value) {
// do something, possibly with m_parent
// nested classes have access to the parent's private members
m_value = new_value;
}
private:
foo* m_parent;
int m_value;
} m_var;
void method() {
int copy = m_var; // ok
m_var = 5; // error
MVar.set(101); // ok
}
};
This doesn't perfectly do what you want, since m_var doesn't really have type int, but it's something to consider.
You can't do exactly you're asking in C++. All variables in a class are visible to all methods in a class, regardless of whether they are public or private.
The question you want to ask yourself is: why would a class want to hide things from itself? The class's interface is the boundary between the class's internal implementation and the services it provides to the outside world. You're either inside the class or outside.
With this in mind, perhaps you use case is such that writing an additional class is the appropriate thing to do?
You can wrap the integer into a special class, and only define setVar(), but not an assignment operator taking an int
class M_type
{
int m_var;
public:
explicit M_type(int m) : m_var{m} {}
operator int() const { return m_var; }
void setVar(int a_var) { m_var = a_var; }
};
class foo
{
M_type m_var;
bool m_isBig;
public:
explicit foo(int m) : m_var{m} {};
void method()
{
int copy = m_var; // OK, calls operator int()
m_var = 5; // error, no operator=(int)
m_var.setVar(101); // OK, calls setVar(int)
doSomething();
}
void doSomething()
{
if(m_var > 5)
{ m_isBig = true; }
else
{ m_isBig = false; }
}
};
Make sure to give M_type an explicit constructor taking an int, and only an implicit conversion operator int() that acts as a "getter". If you make the constructor implicit as well, the compiler-generated assignment operator=(M_type const&) will be able to convert the argument 5 to an M_type.

How should I handle setter methods that shoud only be used by the factory class?

I am using a factory class to produce a number of little classes from memory pools. These little classes are constant once they are returned by the factory.
Currently a typical declaration of one of these little objects goes something like this:
class LittleObject
{
public:
...//non-getter and setter member functions
int getMemberVariable1() const;//should be accessible to everyone
void setMemberVariable1(int newMemberVariable1Value);//should only be accessible to factory class
...//more getters and setters
private:
...
};
So, as you can see the getters and setters are both in the public area. But the only time the values should be set is during the time it is being built by the factory class. Now, I can clearly see one option where I move the setter functions to private access and make the factory a friend of the LittleObject class. I find this option a bit inelegant because it exposes other private member functions to the factory. Private member functions which the factory has no business accessing.
So my question is this: What is the best method making it so that only the factory class can use the setter functions?
I would use a friend class:
class LittleObject
{
friend class LittleObjectFactory;
public:
int getMemberVariable();
private:
void setMemberVariable( int value );
};
I would really prefer to friend the factory, but if you need stronger
encapsulation, at the expense of elegance, mabe it can be done
struct LittleData;
class Factory
{
public:
void MakeLittle(LittleData&);
};
struct LittleData
{
int data1;
float data2;
};
class LittleObject
{
public:
LittleObject(const LittleObject&) = default;
LittleObject& operator=(const LittleObject&) = default;
int GetData1() const { return data.data1; }
float GetData2() const { return data.data2; }
static LittleObject MakeOne( Factory& f )
{
LittleObject obj;
f.MakeLittle(obj.data);
return obj;
}
private:
LittleObject();
LittleData data;
};
Looking at what I just wrote... I really prefer friend
Another possibility is stencils.
By that I mean static instances of each LittleObject preset to the required configuration so that the factory simply needs to make a copy.
The copy can be made via the copy constructor or, if you don't want to make one of those (and the objects are trivial) then you could use memcpy().
Here is an example using copy constructors:
class LittleObject1
{
int a;
int b;
public:
LittleObject1(const LittleObject1& o): a(o.a), b(o.b) {}
LittleObject1(int a = 0, int b = 0): a(a), b(b) {}
static LittleObject1 stencil;
int get_a() const { return a; }
int get_b() const { return b; }
};
LittleObject1 LittleObject1::stencil(3, 7); // preset values
class LittleObject2
{
std::string s;
public:
LittleObject2(const LittleObject2& o): s(o.s) {}
LittleObject2(const std::string& s = ""): s(s) {}
static LittleObject2 stencil;
std::string get_s() const { return s; }
};
LittleObject2 LittleObject2::stencil("hello"); // preset values
class Factory
{
public:
template<typename Type>
Type* create() const
{
return new Type(Type::stencil); // make a copy of the preset here
}
};
int main()
{
Factory fact;
LittleObject1* o1 = fact.create<LittleObject1>();
std::cout << o1->get_a() << '\n';
std::cout << o1->get_b() << '\n';
LittleObject2* o2 = fact.create<LittleObject2>();
std::cout << o2->get_s() << '\n';
}
This would only be useful if the values are preset and don't need calculating at run-time.
Rely on const-correctness
You say the objects are constant when they are returned by the factory.
In that case why not just return const objects:
class Factory
{
public:
std::unique_ptr<const DynamicLittleObject> createDynamicLittleObject();
const AutomaticLittleObject createAutomaticLittleObject();
};
Then just ensuring to write their functionality in a const-correct way will give the correct access control.
Some might worry about the case the user might cast away the constness, but there's only so much that is worth doing to protect them from themselves.
You could make the factory a static member function of each object. So each object type knows how to create itself. Then you can have some kind of template function to make creating them a little less typing.
Something a bit like this:
class LittleObject1
{
int a = 0;
int b = 0;
public:
virtual ~LittleObject1() {}
static LittleObject1* create()
{
LittleObject1* o = new LittleObject1;
o->a = 1;
o->b = 2;
return o;
}
};
class LittleObject2
{
std::string s;
public:
virtual ~LittleObject2() {}
static LittleObject2* create()
{
LittleObject2* o = new LittleObject2;
o->s = "hello";
return o;
}
};
template<typename Type>
Type* createType(Type*)
{
return Type::create();
}
int main()
{
LittleObject1* o1 = createType(o1);
LittleObject2* o2 = createType(o2);
}

C++ Make a generic interface

I have an Interface (there missing a lot of members, but mind the fact this interface is mandatory). I will need 5 classes inheriting from it, which will have a _value attribute. So, ins\
tead of implement 5 classes(for char, short, int, float, double), I thought about a template class :
class my_interface
{
public:
virtual [various_types] getValue() const = 0;
};
template<typename T>
class my_class : public my_interface
{
private:
T _value;
public:
my_class(T value) : _value(value) {} // initialize the attribute on construct
virtual T getValue() const { return _value; }
};
...so that something like that could work :
void my_function()
{
my_inteface* a = new my_class<char>(42);
my_interace* b = new my_class<short>(21);
int result;
result = a->getValue() + b->getValue();
}
But I don't see how I could do. It seems you can't make templates on interface pure virtual. To me, the only way that could work would be to make getValue() to always return a double, since it is the highest sized type I need. However, I don't like that solution.
If you have just one methods (getValue()) on your interface then you only need the template class implementation.
However if you want to an interface like this:
std::string getValue();
int getValue();
long getValue();
Then you are out of luck as you cannot overload a function name based only on the return type. Alternatively you could create a wrapper type.
EDIT
By wrapper type what I mean is that if getValue is required to return multiple types you could do it in a number of ways using a wrapper class that encapsulates your required functionality rather than add it to your top level interface. It could look something like this:
enum ValType{
INT, CHAR, STR, DEQUE
};
class Wrapper{
private:
union S{
int intVal;
char charVal;
std::string stringVal;
std::deque dequeVal;
~S() {}
} theVal;
ValType heldType;
public:
void setVal(int value){ heldType = INT; theVal.intVal = value; }
void setVal(char value){ heldType = CHAR; theVal.charVal = value; }
// ... and so on
int getIntVal() const {
if(heldType!=INT)
throw std::runtime_error("Cop on");
return theVal.int;
}
// and so on
}
Then your interface is
public class my_interface{
virtual Wrapper getVal();
}
You are not really gaining much here as the user will still have to call the correct child member of Wrapper.
You could also just represent the return values as a string if you wanted.
Note that using unions you need to be careful of the caveats:
http://en.cppreference.com/w/cpp/language/union
EDIT 2:
You could do this with a templated return
template<typename = T>
const T& getVal(const T& typeToAllowMethodOverriding) const;
Remember that 'virtual ...' means "make a function pointer in the class that I will use to call the correct derived class". It is just a pointer -- so you have to agree on the return type before you call it. C++ doesn't have the dynamic types and reflection of other languages - it has to know what the return type is before making the call.
You could make class my_interface a template class as well:
template<typename T>
class my_interface
{
public:
virtual T getValue() const = 0;
};
This will generate an interface and a class for every type T that you use.
template<typename U>
class my_interface
{
public:
virtual U getValue() const = 0;
};
template<typename T>
class my_class : public my_interface<T>
{
private:
T _value;
public:
my_class(T value) : _value(value) {} // initialize the attribute on construct
T getValue() const { return _value; }
};
It works for all types but for string type you have to do specialization of templates
I think your best shot will be to use/implement something like boost::variant.
typedef boost::variant<char, short, int, float, double> Value;
class my_interface
{
public:
virtual Value getValue() const = 0;
};
template<typename T>
class my_class : public my_interface
{
private:
T _value;
public:
my_class(T value) : _value(value) {} // initialize the attribute on construct
virtual Value getValue() const { return _value; }
};
Then you could implement the arithmetic operators:
Value operator+(const Value &lhs, const Value &rhs) {
//Check the internal types of lhs and rhs and perform the operation
}
You can also wrap the boost::variant in another class, to provide conversion operators to the basic types.