how to set internals of a class - c++

Hi I am pretty new to C++ and im converting C code to C++. I started by converting all the structs to classes, and added accessors and mutators for the internals, but some structs have other structs inside them. I want to know the best method for setting the internals of a class within a class, such as
struct1.struct2.struct3.i = 5;
where i is an int. Should I be passing as reference using accessors? but seeing as accessors tend to be const would this be something I should do?
something like
class1.get_class2().get_class3().set_i(5) or something if it can be done in this kind of format.
This is probably a dumb question but i have no idea how to do it, Thank You

class1.get_class2().get_class3().set_i(5)
is possible if get_class2() is non-const and returns a non-const pointer reference.
However, this approach completely breaks the encapsulation. The users of class1 should not (and must not) know that class1 uses class2 inside and that in turn uses class3 inside.
If a setter-API is absolutely necessary, then a better approach is do it hierarchically. For example
// User
class1.set_i( 5 );
// class1
class1::set_i( int x ) { class2_obj.set_i( x ); }
// class2
class2::set_i( int x ) { class3_obj.set_i( x ); }
// class3
class3::set_i( int x ) { i_ = x; }

I am not so sure about that ... did you put a class inside a class or an object inside a class ?
something like :
class OBJ1
{
//methods , and other stuff
}
class OBJ2
{
public OBJ1 *O ;
}
is valid , so you can acces a method like :
OBJ2 *N2 ;
N2->O->some_method();
however , something like
class OBJ2
{
class OBJ1;
}
is not valid :P
again... not sure if this is exactly what you asked ...

If you really have a good reason to access your member object via getters and setters, you can do the following:
class A {
public:
void f() const {}
};
class B {
public:
const A &get_a() const {
// the returned reference will be read-only, i.e. only non-const member
// functions can be called, and public members can not be written.
// it needs to be stored in a const A & object.
return a;
}
A &get_writable_a() {
return a;
}
void set_a(A &a) {
//make sure that the assignment operator of A will take care of all the
//dirty internals, such as internal buffers that need to be deleted.
this->a = a;
}
private:
//the member
A a;
};
int main() {
B b;
b.get_a().f();
}
If you don't have a good reason to do so, I'd recommend to simply make it a public member, and access it directy:
class A {
public:
void f() const {}
};
class B {
public:
A a;
};
int main() {
B b;
b.a.f();
}
Isn't that simply much more elegant?
Note that you can use friend to specify other functions or classes that are allowed to directly access your private members.
As was also pointed out in an other answer, in most cases it is a bad idea to make a member object visible to the outside at all.

Related

How can I keep const-correctness and RAII?

I have situation similar to included:
class A
{
public:
A(shared_ptr<B>);
}
class B : public enable_shared_from_this<B>
{
const shared_ptr<A> a;
}
I can't have shared_ptr to B before construction, so before a is initialized. So, I need to initialize my constant field after construction (I think it denies RAII), or just construct it later (so it can't be const, so it denies const-correctness, and also looks like not-too-consistent with RAII).
It looks like propably common situation. Is there any the cleanest way to handle this? How would you do this?
I would solve this by not having const members, plain and simple. They are generally much more trouble than they're worth (they make the class non-assignable, not even move-assignable, for example).
a is private, so only the class itself can access it. Thus it should be enough to document "a should never be modified after being initialised!!!". If you fear that won't be enough (or the class has friends outside your control), you can make this even more obvious like this:
class B : public enable_shared_from_this<B>
{
const std::shared_ptr<A>& a() { return _use_this_ONLY_for_initialising_a; }
std::shared_ptr<A> _use_this_ONLY_for_initialising_a;
};
Such a situation is a good indicator to refactor your code. Think about whether B should actually inhert from A or be a member of A before finding a way around this problem...
.. because it is probably going to be to remove the constness of your object - and probably not use shared_ptr (you have a cyclical reference there, so ref-counting alone will never be able to destroy your objects!).
If A doesn't actually keep a copy of the shared_ptr<B> you pass it (just uses the B briefly) then you can make this work (see below) but:
If A doesn't keep a reference to the B then it could just take a B& or B* argument, not a shared_ptr<B>, so you should change the design.
If A does keep a reference then you're going to have a circular reference, so you should change the design.
This works, but is really, really horrible and would be easy to introduce bugs, and is generally a bad idea, I probably shouldn't even be showing it, just change your design to avoid circular dependencies:
#include <memory>
#include <iostream>
class B;
class A
{
public:
A(std::shared_ptr<B> b);
};
class B : public std::enable_shared_from_this<B>
{
// return a shared_ptr<B> that owns `this` but with a
// null deleter. This does not share ownership with
// the result of shared_from_this(), but is usable
// in the B::B constructor.
std::shared_ptr<B> non_owning_shared_from_this()
{
struct null_deleter {
void operator()(void*) const { }
};
return std::shared_ptr<B>(this, null_deleter());
}
public:
B(int id)
: m_id(id), a(std::make_shared<A>(non_owning_shared_from_this()))
{ }
int id() const { return m_id; }
private:
int m_id;
const std::shared_ptr<A> a;
};
A::A(std::shared_ptr<B> b)
{
std::cout << b->id() << std::endl;
}
int main()
{
auto b = std::make_shared<B>(42);
}

Can I make a variable _const from now on_?

I'm using a library that has a class with an init function distinct from its constructor. Every time I make a new instance I need to call, for example:
MyClass a;
a.init();
Since init is not const, this prevents me from creating const instances (I can't write const MyClass a). Is there some way to call init and then declare from "here on out" (I guess for the remainder of the scope) my variable is const?
This works, but relies on not touching the original variable:
MyClass dont_touch;
dont_touch.init();
const MyClass & a = dont_touch;
If you're using C++11 you could use a lambda function
const MyClass ConstantVal = []{
MyClass a;
a.init();
return a;
}();
This allows you to keep the initialization in place while never giving outside access to the mutable object.
see also:
http://herbsutter.com/2013/04/05/complex-initialization-for-a-const-variable/
You can create a wrapper class and use that instead.
If MyClass has a virtual destructor you can feel safe deriving from it like this:
class WrapperClass : public MyClass
{
public:
WrapperClass()
{
init(); // Let's hope this function doesn't throw
}
};
Or write a class that contains the MyClass instance
class WrapperClass
{
public:
WrapperClass()
{
m_myClass.init(); // Let's hope this function doesn't throw
}
operator MyClass&() {return m_myClass;}
operator const MyClass&() const {return m_myClass;}
private:
MyClass m_myClass;
};
Or write a template to solve this general problem using one of the two solutions above: eg.
template <class T> class WrapperClass : public T
{
public:
WrapperClass()
{
T::init();
}
};
typedef WrapperClass<MyClass> WrapperClass;
Create a function that wraps the first two lines and gives you an object that is ready to go.
MyClass makeMyClass()
{
MyClass a;
a.init();
return a;
}
// Now you can construct a const object or non-const object.
const MyClass a = makeMyClass();
MyClass b = makeMyClass();
Update
Using makeMyClass() involves construction and destruction of a temporary object everytime the function is called. If that becomes a significant cost, makeMyClass() can be altered to:
MyClass const& makeMyClass()
{
static bool inited = false;
static MyClass a;
if ( !inited )
{
inited = true;
a.init();
}
return a;
}
It's usage, as described earlier, will continue to work. In addition, once can also do this:
const MyClass& c = makeMyClass();
You can actually do it quite simply, even without C++11 and lambdas:
const MyClass a;
{
MyClass _a;
_a.init();
std::swap(const_cast<MyClass&>(a), _a);
}
The use of const_cast is admittedly a bit of a hack, but it won't break anything as const is quite a weak specifier. At the same time, it is quite efficient, as the MyClass object is only swapped, not copied (most reasonable expensive-to-copy objects should provide a swap function and inject an overload of std::swap).
Without the cast, it would require a helper:
struct Construct_Init {
operator MyClass() const
{
MyClass a;
a.init();
return a;
}
};
const MyClass a = Construct_Init();
This can be like this in a function (the Construct_Init structure needs not be declared at namespace scope), but it is a bit longer. The copy of the object may or may not be optimized away using copy elision.
Note that in both cases, the return value of init() is lost. If it returns a boolean where true is success and false is failure, it is better to:
if(!a.init())
throw std::runtime_error("MyClass init failed");
Or just make sure to handle the errors appropriately.

Setting readonly property from another class

Suppose I have my classes as:
namespace scope
{
class A
{
private:
int a;
public:
...
};
class B
{
public:
...
A method();
...
};
};
The method definition:
A B::method()
{
A object;
object.a = 3; // private member access error
// access via object (pointer) error if inheritance is used
return object;
}
The most common way to solve the access error is to use setters+getters.
However I don't want any other scope (or someone using the API) to set A.a, so a public setter method is forbidden for this case.
a may be public but it should be read-only on API side. It should be read+write on the source side, because, for instance, I want to set it with B::method. How can I achieve this behaviour?
I tried inheritance, also friend relation. I also played with immutable and const property declarations. The problem with these is, when I declare A object with the default constructor, property is set to some value like -918316838410 (which might arise from the fact that I'm not using extern, I'm not sure) and cannot be set by method later on.
Any ideas will be appreciated. Thanks in advance.
You want B to have access to A that you don't want other people to have?
That is friendship.
Add friend class B, into the class A definition, and all will be happiness.
btw the common examples for this are when I am using multiple classes to generate a single interface. Eg: things like list<> and map<> usually need node classes, and those classes often want friend access on each other. This breach of encapsulation is fine, since they are really one big class from a logical perspective.
Be warned, most people should use friends rarely or never, its mostly for library writers, not for general programming.
Just like Richard said, you can use friendship. But keep in mind that when you need friendship, you should probably think again about your design. As Richard saids too, maybe putting a as a parameter of A constructor should do exactly what you want.
Here is a working example with friendship :
#include <iostream>
namespace scope
{
class A{
friend class B;
private:
int a;
public:
void print(){
std::cout << a << std::endl;
}
};
class B{
public:
A method(){
A a;
a.a=3;
return a;
}
};
int main(){
scope::B b;
scope::A a = b.method();
a.print(); //just to see it works...
}
Here is a way to do the same without friendship and keeping a private (Ok its ugly :-)
#include <iostream>
namespace scope
{
class B;
class A
{
private:
int a;
public:
void print(){
std::cout << a << std::endl;
}
// A way to only allow B instances to give a correct value
// of "a" member
void pleaseClassBSetMyPrivateMember(B& b);
};
class B
{
public:
A method(){
A a;
a.pleaseClassBSetMyPrivateMember(*this);
return a;
}
int computeValueForMemberOfClassA(A& a){
// you can access public members of a to
// calculate the proper value of a.a member
return 3;
}
};
void A::pleaseClassBSetMyPrivateMember(B& b)
{
// ask for class B object the correct value for member a
a = b.computeValueForMemberOfClassA(*this);
}
};

How to pass a linc to class function and call it?

So I have a class like
class mySafeData
{
public:
void Set( int i )
{
myMutex.lock();
myData = i;
myMutex.unlock();
}
void Get( int& i)
{
myMutex.lock();
i = myData;
myMutex.unlock();
}
private:
int myData;
boost::mutex myMutex;
};
its instance is running. Lets call instance A. I want to create a new class that would take as a start up argument some kind of link to Getter from A and would be capable to somehow save link to thet getter for calling it inside its private methods vhen needed. how to do such thing?
Sounds like you want something like this:
class myOtherData
{
public:
myOtherData(mySafeData& dataSource) :
myDataSource(&dataSource)
{}
private:
// note that if you take the advice in the comments,
// you don't need this wrapper function at all,
// it's simple just to call myDataSource.Get()
int GetData()
{
int result;
myDataSource.Get(result);
return result;
}
mySafeData* myDataSource;
};
mySafeData a;
myOtherData b(a);
// b uses a as its data source (make sure it lives as long!)
I'm not sure what you mean by linc/link. Are you asking for anything more than this pattern?
class Foo {
public:
Foo(mySafeData& d) : data(d) {}
int someFunction() {
int i;
data.get(i);
return i;
}
private:
mySafeData& data;
};
...
Foo f(a);
What's wrong with pointers? Smart, Shared, Scoped... I'll use standard pointers for now.
class B
{
public:
B(mySafeData* ptr) // constructor takes a memory pointer as parameter
:SafeData_ptr(ptr)
{
SafeData_ptr->foo(); // call public function from class A
}
~B() // destructor
{
}
private:
mySafeData* SafeData_ptr; // will hold the mem address of instance A when
// this class is initialized
};
Later on your code, when you have instance A ready, you would do something like this:
B b_demo(&A); // &A passes the memory address of the instantiated object
// and A::foo() will be automatically called when B is constructed.
This is probably not the smartest way to do it, but I think it illustrates the idea.

Non static members as default parameters in C++

I'm refactoring a large amount of code where I have to add an extra parameter to a number of functions, which will always have a value of a member of that object. Something like
class MyClass
{
public:
CMyObject A,B;
void MyFunc(CMyObject &Object);
// used to be void MyFunc();
};
Now, I'd actually like it to read
class MyClass
{
public:
CMyObject A,B;
void MyFunc(CMyObject &Object = A);
};
But I'm not allowed to have a default parameter that is a non-static member. I've read this similar question which suggest this isn't possible, but I'm wondering if there is any reasonable workaround. Reason being that 95% of the time the default parameter will be used, and thus using a default parameter would hugely reduce the amount of code I have to change. My best solution so far is something like this;
class MyClass
{
public:
CMyObject A,B;
void MyFunc(BOOL IsA = TRUE);
};
void MyClass::MyFunc(BOOL IsA)
{
CMyObject &Object = A;
if (!IsA)
Object = &B;
}
This is less than elgant, but is there a better way of doing this that I'm missing?
Edit: FWIW, the reason for the extra parameter is to externalize some state related members from the object in question to aid multi-threading.
How about :
class MyClass
{
public:
CMyObject A,B;
void MyFunc()
{
MyFunc(A);
}
void MyFunc(CMyObject &Object);
};
?
Another way:
class MyClass
{
public:
MyObject A,B;
void MyFunc(MyObject MyClass::*myObject = &MyClass::A) {
MyObject& obj = *(this->*myObject);
}
};
This makes it even impossible to pass in an MyObject member from another MyClass instance. Your three valid options to call MyFunc are .MyFunc(), .MyFunc(&MyClass::A) and .MyFunc(&MyClass::B)