How to make inaccessible class variable - c++

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.

Related

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.

Accessor functions by data member assignment

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.

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);
}

Make variable read-only after initialization in another function/constructor [C++]

I have a class in A.h file:
class A {
...
public:
A();
...
private:
bool t = false;
...
}
In the A.cpp file:
A::A() {
...
t = true; <- after this point, have t be const or readonly
...
}
Is this possible? Or would I have to use a different value?
Unfortunately you can't do it in this way.
However you can still do what you want to do (you can change the exact mechanism to suit your precise needs since you weren't quite clear):
class A {
...
public:
A();
...
private:
bool A::init_A_impl();
const bool t_;
...
};
bool A::init_A_impl()
{
bool t = false;
...
t = true; <- after this point, have t be const or readonly
...
return t;
}
A::A() : t_(init_A_impl())
{
}
In-class initialization of members works in C++11:
class A {
public:
A();
private:
const bool t = false;
};
Before C++11, you'd use member initializer list:
class A {
public:
A() : t(false) {}
private:
const bool t;
};
But const data members are unusual thing. For one, they make your class non-assignable (if you rely on compiler generated assignment operator). Just have the member private and don't let the interface provide the means to change it.

const function inherited

Suppose I have a base class foo
class foo {
virtual int get() const = 0;
}
and maybe 20 sub-classes foo_1, foo_2 ... inherited from foo and in the form of:
class foo_1 : public foo {
int get() const { return 1; }
}
...
class foo_20 : public foo {
int get() const { return 20; }
}
Suddenly life is not so easy! I have a class foo_21, which has to do this:
class foo_21 : public foo {
int get() { member_ = false; return 0; }
bool member_;
}
The problem is get is declared as const in the base class, and I have to change
something in the sub-class foo_21. How could I find a way to go around it?
Your base function isn't virtual, which makes all this highly speculative. Your code should already be working as you posted it (though maybe not as you expect).
You could use mutable members:
class foo_21 : public foo
{
int get() const { member_ = false; return 0; }
mutable bool member_;
};
It's important that the mutable variable doesn't affect the logical constness of your class. If it does, you should rework your design.