Make a member variable object modifiable but not assignable - c++

I've searched high and low for the answer for this, perhaps I'm just not using the right terms to get any results?
Is there any way to make it so that a member variable is const in that it can't be reassigned, and will always be the same object, but still allow the object itself to be modified? Much like the behavior of a const pointer to a non-const object, but without being an actual pointer?
The main use case that I see for this would be composition. Let's say Foo has-a Bar, and you want to be able to access and modify that Bar, but not change which Bar Foo has. Just change the properties/call non-const methods on that Bar. Is there any way to do this?

Not with const correctness machinery; it's too primitive for that (it's just a single bit: either "change" or "not change").
You can however mark assignment private and the container a friend so that only container methods will be allowed to assign, but mutators could be marked public for others to use.
class Foo {
public:
int x, y;
Foo() : x(0), y(0) {}
friend class Bar;
private:
Foo& operator=(const Foo& other){
...
return *this;
}
};
class Bar {
public:
Foo foo;
Bar(){
foo = Foo(); // OK from here
};
};
void baz() {
Bar bar;
bar.foo.x = 42; // Ok assigning a member of foo
bar.foo = Foo(); // Invalid from here (doesn't compile)
}

Normally you would just do
struct Foo {
Bar bar;
};
Each Foo object then has a Bar subobject, which is contained within Foo itself, and whose address does not change. Assigning to bar invokes Bar's assignment operator; it doesn't change the location of bar.
If you need polymorphic behaviour from the Bar, you would do
struct Foo {
const std::unique_ptr<Bar> bar;
};
Here, since the std::unique_ptr is const, it cannot be made to point to a different Bar object after Foo's initialization, but since the Bar itself is not const, it can be modified. You could also use const std::shared_ptr<Bar>.

My best guess is that you can make the member private and then use setter member functions that achieve the mechanics that you desire (i.e. the end user can only modify your member variables in the way that you want them to be modified).

Related

Initialize a C++ class using its constructor inside another Classes constructor that references it

I have a class Foo that references Bar:
class Foo {
Bar &bar;
};
and bar requires an int& to be constructed:
Class Bar {
Bar(int& required_int);
}
I want to be able to initialize Bar when I initalize Foo, but I cannot seem to do so using either of the following:
Foo::Foo(int &my_int) : bar(my_int) {
//...
}
Foo::Foo(int &my_int) : bar(new Bar(my_int)) {
//...
}
Because the compiler complains that whatever is inside bar(...) must be an lvalue. Is this initalization chaining possible? I don't see how bar(...) could ever contain an lvalue if my instance of Bar doesn't exist yet.
class Foo {
Bar & bar;
};
Here bar can only refer to an existing Bar object as it's a reference. You cannot initialize it yourself in Foo class. So, a valid ctor would be similar to this:
Foo::Foo(Bar & existingBar) : bar(existingBar){}
If you want Foo class to have its own independent Bar object, then remove the reference and initialize it like you're doing already.

Only allow access to an object's members, not the object itself

Given the following class:
class Foo
{
public:
//...
private:
Bar mBar;
};
Is it possible to expose the mBar member in such a way that it's members can be accessed, but not the mBar object itself?
The reason is that users should be able to access all of mBar's members but they should not be able to assign another Bar instance to mBar.
Bar has a lot of members and it would be cumbersome to write getters/setters and forwarding fuctions for them all. But if mBar is made public one is able to do aFoo.mBar = Bar(/*...*/);which is the only thing that should not be allowed.
Deleting Bar's assignment operators is not an option.
if you only want to protect against errors and not Machiavelli, operator-> might help (you might probably want a wrapper instead of directly put it in foo though):
class Foo
{
public:
//...
const Bar* operator ->() const { return &mBar; }
Bar* operator ->() { return &mBar; }
private:
Bar mBar;
};
so
Foo foo;
foo->bar_member;
foo.foo_member;
// Machiavelli
*foo.operator->() = Bar();
I would probably rethink your design but here is a possible indirect way using an intermediate get method:
struct Bar {
int intAttr;
};
class Foo {
Bar mBar;
public:
template <class U>
U& get(U Bar::* p) {
return mBar.*p;
}
};
This way, you can access any public member of mBar using:
Foo foo;
foo.get(&Bar::intAttr); // get
foo.get(&Bar::intAttr) = 0; // set

Initialize static member inside constructor of an instance

I want to initialize a static member variable inside the constructor of a particular instance. Is that a bad idea?
The situation is as follows. I have a static member variable that all instances of this class should share. Normally, I'd just use a static initializer. But, I don't have the necessary information needed to construct the static object until the constructor gets called. But of course, I don't want to create a new object every time the constructor gets called, so I want to do something like this.
class Foo
{
static Bar * bar;
Foo( Xyz xyz);
};
Bar * Foo::bar = nullptr;
Foo::Foo(Xyz xyz)
{
if (Foo::bar == nullptr)
{
// initialize static bar
Foo::bar = new Bar(xyz);
}
}
I know of course xyz migth be different for different calls to the constructor of Foo. That doesn't matter for me.
Is this bad software design? I feel a little weird initializing a static object inside the constructor. But it's not that different from the singleton design pattern. So maybe it is ok?
EDIT
Thanks for the comments guys. It seems like people are not a fan of this design. I will modify it so that I create a Bar once before the very first instantiation of Foo, and pass a Bar * as a parameter in Foo's constructor. Each Foo will have a pointer to a Bar, and I'll make sure all Foos are all pointing to the same Bar. Is that better?
Is this bad software design?
In general it would be considered so, yes. There are many reasons why the Singleton Pattern or having static variables in this way is considered bad design.
But it's not that different from the singleton design pattern. So maybe it is ok?
If you really want to make that a Singleton Pattern you should rather use Scott Meyer's technique:
class Foo
{
static Bar* bar(Xyz xyz) {
static Bar barInstance(xyz);
return &barInstance;
}
Foo( Xyz xyz) : xyz_(xyz) {}
void baz() {
Bar* b = bar(xyz_);
// use b ...
}
private:
Xyz xyz_;
};
This code will be thread safe, and avoids the need to check for a nullptr.
Though Bar should make up a Singleton on it's own then, and you use it in Foo whenever needed:
class Bar {
public:
static Bar& getInstance(Xyz xyz) {
static Bar barInstance(xyz);
return &barInstance;
}
private:
Bar(Xyz xyz) : xyz_(Xyz) {}
Bar(const Bar&) delete;
Bar(Bar&&) delete;
Bar& operator=(const Bar&) delete;
Bar& operator=(Bar&) delete;
Xyz xyz_;
};
class Foo {
public:
Foo(Xyz xyz) barRef(Bar::getInstance(xyz)) {
// ^^^ Notice 1st instance of Foo created
// wins to create the Bar actually
}
private:
Bar& barRef;
};

Initialize const member variables

I have C++ code that boils down to something like the following:
class Foo{
bool bar;
bool baz;
Foo(const void*);
};
Foo::Foo(const void* ptr){
const struct my_struct* s = complex_method(ptr);
bar = calculate_bar(s);
baz = calculate_baz(s);
}
Semantically, the bar and baz member variables should be const, since they should not change after initialization. However, it seems that in order to make them so, I would need to initialize them in an initialization list rather than assign them. To be clear, I understand why I need to do this. The problem is, I can't seem to find any way to convert the code into an initialization list without doing one of the following undesirable things:
Call complex_method twice (would be bad for performance)
Add the pointer to the Foo class (would make the class size needlessly large)
Is there any way to make the variables const while avoiding these undesirable situations?
If you can afford a C++11 compiler, consider delegating constructors:
class Foo
{
// ...
bool const bar;
bool const baz;
Foo(void const*);
// ...
Foo(my_struct const* s); // Possibly private
};
Foo::Foo(void const* ptr)
: Foo{complex_method(ptr)}
{
}
// ...
Foo::Foo(my_struct const* s)
: bar{calculate_bar(s)}
, baz{calculate_baz(s)}
{
}
As a general advice, be careful declaring your data members as const, because this makes your class impossible to copy-assign and move-assign. If your class is supposed to be used with value semantics, those operations become desirable. If that's not the case, you can disregard this note.
One option is a C++11 delegating constructor, as discussed in other answers. The C++03-compatible method is to use a subobject:
class Foo{
struct subobject {
const bool bar;
const bool baz;
subobject(const struct my_struct* s)
: bar(calculate_bar(s))
, baz(calculate_baz(s))
{}
} subobject;
Foo(const void*);
};
Foo::Foo(const void* ptr)
: subobject(complex_method(ptr))
{}
You can make bar and baz const, or make the subobject const, or both.
If you make only subobject const, then you can calculate complex_method and assign to bar and baz within the constructor of subobject:
class Foo{
const struct subobject {
bool bar;
bool baz;
subobject(const void*);
} subobject;
Foo(const void*);
};
Foo::Foo(const void* ptr)
: subobject(ptr)
{}
Foo::subobject::subobject(const void* ptr){
const struct my_struct* s = complex_method(ptr);
bar = calculate_bar(s);
baz = calculate_baz(s);
}
The reason that you can't mutate const members within a constructor body is that a constructor body is treated just like any other member function body, for consistency. Note that you can move code from a constructor into a member function for refactoring, and the factored-out member function doesn't need any special treatment.
You may use delegate constructor in C++11:
class Foo{
public:
Foo(const void* ptr) : Foo(complex_method(ptr)) {}
private:
Foo(const my_struct* s) : bar(calculate_bar(s)), baz(calculate_baz(s)) {}
private:
const bool bar;
const bool baz;
};
If you don't want to use the newfangled delegating constructors (I still have to deal with compiler versions that don't know about them), and you don't want to change the layout of your class, you could opt for a solution that replaces the constructor with const void * argument by a static member function returning Foo, while having a private constructor that takes the output from complex_method as argument (that latter much like the delegating constructor examples). The static member function then does the necessary preliminary computation involving complex_method, and ends with return Foo(s);. This does require that the class have an accessible copy constructor, even though its call (in the return statement) can most probably be elided.

global static variable vs static variable in function?

What's the diference between use:
static Foo foo;
// ...
foo.func();
And:
Foo& GetFoo(void)
{
static Foo foo;
return foo;
}
// ...
GetFoo().func();
Which is better?
The principal difference is when construction occurs. In the first case, it occurs sometime before main() begins. In the second case, it occurs during the first call to GetFoo().
It is possible, in the first case, for code to (illegally) use foo prior to its initialization. That is not possible in the second case.
A GetFoo is generally used when you don't want copies of your class/object.
For example:
class Foo
{
private:
Foo(){};
~Foo();
public:
static Foo* GetFoo(void)
{
static Foo foo;
return &foo;
}
int singleobject;
};
You can externally access singleobject via Foo::GetFoo()->sinlgeobject. The private constructors and destructors avoid your class getting copies created.
For the use of static Foo foo, you must have public constructors declared which means you are always accessing your class by it, but your class will also be able to get copies.