I'm a Java developer trying to pick up C++. Is it okay to use a setter inside a constructor in order to reuse the sanity checks the setter provides?
For example:
#include <stdexcept>
using namespace std;
class Test {
private:
int foo;
void setFoo(int foo) {
if (foo < 42) {
throw invalid_argument{"Foo < 42."};
}
this->foo = foo;
}
public:
Test(int foo) {
setFoo(foo);
};
};
Yes, it is recommended to do this, basically for the reason you already mentioned.
On the other hand you should ask yourself if you need the setter at all and not directly implement the checks inside the constructor. The reason I am writing this is that setters in general result in mutable state which has many disadvantages as opposed to immutable classes. However sometimes they are required.
Another recommendation: If your class variable is an object and you can modify the constructor of this object, you could put the check into the constructor of this object:
class MyFoo {
public:
MyFoo(int value) {
if (value < 42) {
throw invalid_argument{"Foo < 42."};
}
v = value;
}
private:
int v;
}
This will enable you to use an initialization list in the constructor of your Test class:
Test(int foo) : foo(foo) {}
However, now the check is a property of the class of the variable and no longer one of the owning class.
Yes you can. It's fine as long as your setters are not virtual, because it's inheritance hierarchy in calling right functions as the "this" ptr is not ready yet.
Here is Herb Sutter GOTW on this matter: http://www.gotw.ca/gotw/066.htm
Yes, that's fine as long as it makes sense to have a setter for a particular member variable (have some logic that can't be checked by assignment only for example) . In this example, setFoo could've just taken an unsigned int and the caller would know not to pass negative values. Which in turn could eliminate the check and thus the need for a setter. For more elaborate checks, a setter and usage of that setter in the constructor is just fine.
Short answer: Yes. In fact, your example works.
Long answer: But it is not a good practice. Al least, you have to take care.
In general, a set function works with a constructed object. It is supposed that the invariant of the class holds. The functions in a class are implemented considering the invariant is true.
If you want other functions to be used in a constructor, you would have to write some code. For example, to create an empty object.
For example, if in your class you change setFoo in the future (let's say setFoo changes the member foo only it is larger) you example stop working.
This is okay.
The only situation you cannot call member function is when the base classes are not constructed yet.
can member functions be used to initialize member variables in an initialization list?
I know this doesn't fit your situation. Its just for the sake of completeness:
When you are simply settings member values (without checks like yours in setFoo) it is recommended to use initialization lists in the constructor. This prevents members being "initialized" 2 times: 1. with their default value, 2. with the value that you passed into the constructor.
class Test {
private:
int foo_;
public:
Test(int foo)
: foo_(foo)
{ };
};
Related
I cannot figure a way to do this in the general case. Say that I have 2 classes and they maintain pointers to each other:
class first {
unique_ptr<second> p2;
public:
first() : p2(this) {}
};
class second {
first* p1;
public:
second(first* arg) : p1(arg) {}
};
This all works fine and dandy, but what I really want is to use a shared_ptr as a part of second because second objects may also be created independently of first. They will just be passed a pointer to a first on construction, but they won't know if it's gone.
I can't just make second::p1 a shared_ptr because I wouldn't know how to pass in this from first::first().
Is there an idiom that can help me handle this?
It is possible with the caveat that you can then only create instances on the heap. Using std::shared_from_this would be a nice solution but it can only be called once a std::shared_ptr to the object exists which is not possible until the constructor has finished, even when using std::make_shared and a std::bad_weak_ptr exception is thrown.
Instead we ensure that the only way to create an instance of this class is through a static function which does the necessary setup.
#include <cassert>
#include <memory>
class second;
class first {
struct Unconstructable {};
std::unique_ptr<second> p2;
public:
first(Unconstructable) : p2() {}
static std::shared_ptr<first> create() {
Unconstructable u;
auto f = std::make_shared<first>(u);
f->p2 = std::make_unique<second>(f);
return f;
}
};
class second {
std::shared_ptr<first> p1;
public:
second(std::shared_ptr<first> arg) : p1(arg) {}
};
int main()
{
auto f = first::create();
}
Edit: The use of Unconstructable isn't really necessary but is required for the use of std::make_unique. If I were to simple make the constructor private then std::make_unique would fail to compile even if I made it a friend function since the implementation uses internal helper functions. Having a private struct as a constructor argument is a way to bypass this while still preventing construction from happening outside of the class itself.
Copying from my comments as OP indicated this is an answer he is OK with.
Unfortunately, there is no safe way of doing so - for the simple matter of constructor not having a slightest idea how an object was allocated. What if it was not allocated dynamically at all?
enable_shared_from_this, as indicated in another comment, is not a solution either - it just allows to get a shared_ptr from a weak_ptr hidden inside the class. However, this is only safe as long as there is at least one shared_ptr already created and holding the lock - and again, this is not something which can be ensured from the constructor.
A. How useful/cumbersome is the following trick of using the same function for getter as well as setter, by returning a reference?
B. How good is the practice of adding const to the end of function declarations in case of getters and setters?
#include <iostream>
class A
{
int varReadWrite_;
int varReadOnly_;
int varRestricted_;
public:
A() : varReadOnly_(25) {}
virtual ~A() {}
int& varReadWrite() { return varReadWrite_; }
int varReadOnly() { return varReadOnly_; }
int varRestricted() { return varRestricted_; }
void setVarRestricted(int i); //throwable
};
int main(int argc, char *argv[])
{
A a;
a.varReadWrite() = 45;
std::cout << a.varReadOnly() << a.varReadWrite() << std::endl;
return 0;
}
The reasons, why I chose this design was:
ease of access of explicitly read-only or explicitly writable variables.
the restricted (I dont know what else to call them), the variables, that require sanitization and filtering before being assigned -- these variables might require an explicit setter.
Using boost fusion map is also an interesting possibility as shown here
Update
Const Reference Members are interesting for read-only access to variables, e.g.
class A {
int mA;
public:
int& a;
A(int a_ = 0) : mA(a_), a(mA) {}
};
Practically this comes with the extra effort to code the copy and move constructors, which is an acceptable compromise for me.
Cpp Reference Copy Construtor says
The implicitly-declared or defaulted copy constructor for class T is defined as deleted if... T has non-static data members that cannot be copied (have deleted, inaccessible, or ambiguous copy constructors);
A. How useful/cumbersome is the following trick of using the same function for getter as well as setter, by returning a reference?
Returning a reference to your internal members in general is not recommended since this way you give an easy access to others so they could change your object internal state without using any method provided by the object's class API. Thus, it will be very difficult to track this kind of changes in the code. In general changes in the internal state of an object should only be possible through methods that belongs to the class API.
B. How good is the practice of adding const to the end of function declarations in case of getters and setters?
if you refer to adding const for methods like:
void PrintState() const
Then in general this doesn't make sense for setters. Const in this case means This method doesn't change the object state. So it's a commitment that you give to the caller to say: I will not change the object state by this call. In general it's very good practice since it helps you during the design to think about your methods and see which one is really modifying the object state or not. Additionally, it's a defensive programming since
it's recursive: if you pass this object to some method by reference (through a pointer or reference) he can't call const methods unless this method is marked as const also. So this prevents from changing the object state by error.
Accessors (a.k.a getters and setters) are as good/cumbersome as having public member variables, as you've just violated encapsulation and lied yourself. Mixing them in a single function is even worse, as the caller may hold the returned reference, opening the hole for even more subtle bugs than described in the link above.
Secondly, adding const to a member function declaration will protect you from setters, but not from getters. Anyway, plan your designs better off :).
I wrote a class where the constructor is private.
I need to assign the given value to the private members ONLY ONCE
in the method construct(int a).
It should be something like a constructor but not a constructor !
Every time this construct(int a) is called after the first time,
I do not need to reassign anything to that specific OBJECT.
How to achieve that without any booleans?
I thought of boost::call_once but it calls construct(int a) once for ENTIRE CLASS! and I need to call this function ONCE for EACH OBJECT.
just like ctor! Any ideas?
UPDATE 1:
The Constructor is private. But the class has some members those values can be assigned from the outside but only ONCE
I am trying to achieve some automatisation for checking if a function was called or not already without using bool wasCalled or something like that.
UPDATE 2:
LT::Pointer lut = LT::New();
std::vector<double> points;
....
lut->construct(points);
The second time
lut->construct(points);
is called - error should be given, or just somehow make it impossible.
Direct Answer:
You can devise a wrapper that applies "assign-once" semantics to the wrapped object.
However, you can not make the compiler detect that a value is being set for the second time at compile time, so you should be prepared to make it assert/throw at runtime.
Background/look around
As others have said, this smells very much like a design flaw. Why can't you have the New operation forward constructor parameters (a-la make_shared, make_unique?):
template <typename T, typename... Args>
SmartPointer<T> genericNew(Args&&... args) {
return SmartPointer<T>(new T(std::forward<Args>(args)...));
}
Of course, there could be specialized factory methods that even know how to set private properties after construction. Make the factory methods friends, to preven others from using the hidden property (setters) after creation by the factory:
struct X {
int a;
X(int i) : a(i) {}
typedef SmartPointer<X> Ptr;
static Ptr New(int a, int init_only) {
Ptr p(new X(a));
p->init_only = init_only;
return p;
}
private:
int init_only;
};
(here I opted to make the New factory method a static member, so it's implicitly a friend)
I create a class like this
class myClass {
public:
int addMeOne;
void Invoked() { .... }
};
I created an object of it and used to send it to all other modules of my program by reference . Everyone used to increment the addMeOne variable by 1 . some even used to add twice but that’s not the point .
With this , now I want whenever someone alters addMeOne , my function Invoked() should get called .
Please note that the right strategy would have been that I should have allowed addMeOne to be exposed outside by some function and inside that function I could call Invoked . However , the interface cannot be altered now since this is now exposed to the all others and should not be modified. How can I correct this . ?
You have to make a method that would assign the value to the addMeOne variable, this is known as a setter method, and make the variable itself private.
There is no way to trigger a function upon changing an integer variable, I believe.
One alternative which would change the interface, but would not require changing the code outside is to define a class that would mimic the behavior of an integer, i.e. implement operator++ etc., and change addMeOne to this type.
You needv to read up on encapsulation. Without providing a locked down getter / setter interface to addMeOn there is no way to guarantee control over its use.
Don't be afraid to change the interface. It will not be a big task for anyone using it to change and they should be clear that what you are doing in changing it is to provide value for their benefit.
Should you preserve the ABI of this class, or just the syntax that its clients use?
If you can change the type of addMeOne, preserving the ability to write addMeOne++ etc, you can define a class and the relevant operators for it - then make addMeOne to be an instance of this class. Certainly, now addMeOne operators can do anything -- including invocations of some MyClass member functions.
Psuedo-code:
class Proxy
{
public:
Proxy(YourClass *parent) : parent_(parent), value_(0)
{}
void operator++()
{
++value_;
// doAnything with parent_
}
// accessors, cast operators etc...
private:
YourClass *parent_;
int value_;
};
class YourClass
{
public:
YourClass() : addMeOne(this)
{}
Proxy addMeOne;
};
Really, it's probably worth telling all clients to use a method instead of a public variable. You either need to change the class, the clients or both.
There's no way around it. Do it again and do it right. Take the hit.
There are tricks: Once you expose a member variable one thing that you can do is to replace int addMeOne with some other variable with the same name but a different type. countedint addMeOne. The countedint class you would have to write such that it behaves like an int but that the assignment, incrementation and so on also counts the number of times they have been used. For example
countedint & operator ++(){
m_value++;
m_number_of_uses++;
return *this;
}
countedint & operator --(){
m_value--;
m_number_of_uses++;
return *this;
}
You would probably also need to have a cast operator to int and you could count the number of uses there too.
Use can turn addMeOne into a proxy.
class myClass
{
class addMeOneProxy
{
public:
addMeOneProxy(myClass &s) : parent(s) {}
// This gets called whenever something tries to use the addMeOne
// member variable as an integer.
operator int() const
{
return parent.addMeOne;
}
// This gets called whenever something assigns a value to addMeOne.
int operator=(int val)
{
parent.Invoked();
return val;
}
// You could also implement an operator++ or whatever else you need.
private:
myClass &parent;
};
public:
void Invoked();
addMeOneProxy addMeOne;
};
Of course, if you decide to make Invoked() private at some point, you will need to make myClass a friend class of addMeOneProxy so that addMeOneProxy can call the Invoked member function.
I certainly concur with the other commenters that you should really have getter and setter functions for this, but I also understand that developers often have limited power to control and change the world they live in. So, the proxy is how you can do it if you aren't able or allowed to change the world.
I make pretty extensive use of PImpl and something that I've found myself waffling on is where exactly to to initialize members of the Pimpl struct. Options are to create a constructor for the Private struct and initialize them there, or to initialize them in the main class's constructor.
myclass.hpp:
class MyClass {
public:
MyClass();
~MyClass();
private:
struct Private; unique_ptr<Private> p;
};
myclass.cpp:
#include "myclass.hpp"
#include <string>
struct MyClass::Private {
int some_var;
std::string a_string;
// Option A
Private() :
some_var {42},
a_string {"foo"}
{}
};
MyClass::MyClass() : p(new MyClass::Private) {
// Option B
p->some_var = 42;
p->a_string = "foo";
}
At present I don't really see a difference between the two other than if I were, for some reason, to want to create new Private objects or copy them around or something, then Option A might be preferable. It also is able to initialize the variables in an initialization list, for what that's worth. But, I find that Option B tends to be more readable and perhaps more maintainable as well. Is there something here I'm not seeing which might tilt the scales one way or the other?
By all means, follow the RAII approach and initialise members in your Private type. If you keep stuff local (and more importantly, at logical places), maintenance will thank you. More importantly, you will be able to have const members, if you use Option A.
If you have to pass values from your MyClass ctor, then do create a proper constructor for Private:
struct MyClass::Private {
int const some_var; // const members work now
std::string a_string;
// Option C
Private(int const some_var, std::string const& a_string) :
some_var {some_var},
a_string {a_string}
{}
};
MyClass::MyClass() : p(new MyClass::Private(42,"foo")) {
}
Otherwise your Private members will be default constructed, only to be overwritten later (which is irrelevant for ints, but what about more complicated types?).
As already noted by #Charles Salvia above, assignment in any of the two constructors incurs some overhead, as the variables are default-constructed before the value is assigned. The amount of this overhead of course strongly depends on the type of your variables.
If you can accept this, I think going for the most readable version is the best. So, if you find assignment in MyClass's constructor the most readable, go for it.
However, take into account that there is no way around an initializer list (for the Private c'tor), namely when your member variables do not have a default constructor or when you use references or constants.
You might want to decide this from case to case, but "always" using initializer lists will keep things consistent and future-proof for newly added data members.