How to properly initialize non-default-constructible class member? - c++

Assume I define a class Foo, which does not implement a default constructor.
In addition, I have a class Bar, which "owns" an instance of Foo:
class Foo() {
private:
int m_member;
public:
Foo( int value ) : m_member(value) { }
};
class Bar() {
private:
Foo m_foo;
public:
Bar( /* ... */ ) {
int something;
/* lots of code to determine 'something' */
/* should initialize m_foo to 'Foo(something)' here */
}
};
The code as shown won't run, since Bar is trying to call the default constructor of Foo.
Now what I am trying to do is to have the constructor of Bar first determine something and then pass the result to the constructor of Foo.
One way to solve this is to have Bar only own a reference/pointer to Foo and initialize it after m_something was determined. However, I'd like to avoid that to make clear that the lifetime of m_foo is completely dependent on the lifetime of the owning class.
Another way would be to implement a default constructor in Foo and set the value later, which I would also like to avoid, since any instance of Foo should have a valid value for it's member (at any time).
What is the proper way to implement this? Am I stuck with a reference/pointer here?

The best idea will be to create helper function, that will calculate something and then just initialize m_foo in constructor initialized list.
class Bar {
private:
Foo m_foo;
public:
Bar( /* ... */ ) : m_foo(calculate_something()) {
}
private:
static int calculate_something()
{
int something = 0;
// lot of code to calculate something
return something;
}
};

Does this complex initialization code actually belong to Bar? It may be good to consider having a separate class to just do this initializing. Something like
class Bar {
public:
Bar(int param, Foo foo): m_foo(foo) {
// do just some very simple calculations, or use only constructor initialization list
}
...
}
class BarBuilder {
public:
BarBuilder(/*...*/) {
// do all calculations, boiling down to a few parameters for Bar and Foo
Foo foo(fooParameter);
m_result = new Bar(barParameter, foo); // give Foo here explicitly
}
Bar getResult() { return *m_result; }
private:
Bar* m_result; // or better use unique_ptr
}
This also opens the way to a full Builder pattern that might be useful in case, for example, you do not always need all that complex calculations.
This assumes all classes to be copy-constructible, but you may more-or-less easily modify it to support what you need.

Related

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

Make a member variable object modifiable but not assignable

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).

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

What method do you use to initialize member variables?

Suppose I have a class Foo, with a member variable that is a std::vector of floats, bar. I then create an instance of Foo, called foo. Let's say that I do not know the length of bar before the program runs, but at the point when foo's constructor is called, I know that it's length should be x.
There are three ways I can think of to initialize the length of bar, and I'm just wondering which of the three most people tend to use. I have ranked them in order of what I would consider to be "best practice", but I'm more curious about what method people "actually" use in practice. Sometimes I use methods which make the code clearer to follow, rather than necessarily following best practice...
bar is a private member, and I resize it during foo's constructor, e.g. Foo foo(x){bar.resize(x)};
bar is a private member, and I call foo.ResizeBar(x) which resizes bar internally, after creating foo.
bar is a public member, and I call foo.bar.resize(x), after creating foo.
Or, in code:
1.
class Foo
{
private:
std::vector<float> bar;
public:
Foo(int x)
{
bar.resize(x);
};
};
int main()
{
Foo foo(100);
return 0;
}
2.
class Foo
{
private:
std::vector<float> bar;
public:
Foo()
{
};
void ResizeBar(int x)
{
bar.resize(x);
};
};
int main()
{
Foo foo;
foo.ResizeBar(100);
return 0;
}
3.
class Foo
{
public:
std::vector<float> bar;
Foo()
{
};
};
int main()
{
Foo foo;
foo.bar.resize(100);
return 0;
}
The problem with all three of your methods is that you're needlessly invoking the default initializer for your vector, and then modifying the already initialized vector to suit your needs.
You should be invoking the correct initializer using the initializer list:
Foo::Foo(std::size_t x) : bar(x, 0) { }
The best method is not in the list of options you posted. The best method is to initialize bar using member initializer lists.
Foo::Foo(int x) : bar(x) {}

Calling the constructor of the base class after some other instructions in C++

As far as I know it is not possible to call the constructor of the base class. The only way I know is this:
MyClass::MyClass(/* args */) : Base(/* args */)
{
// ...
}
but this would invoke the constructor at the beginning.
Is there any way to call it somewhere else in the constructor? Something like this:
MyClass::MyClass(/* args */)
{
// ... instructions
Base::Base(/* args */);
// ... other_instructions
}
According to this What are the rules for calling the superclass constructor? question I understand there is no way but I read here and I guessed it was possible, but if I try I get:
error: invalid use of 'class Base'.
Am I doing something wrong? Is it possible to do this some way or is there any other possible solution to this need?
Thanks!
EDIT: I understand I forgot a key point: the base class is part of a framework, and therefore it would be good not to have to modify it, if possible.
If the base class constructor takes at least one argument, you could use a helper function like this:
int DoStuffBeforeCtorAndForwardInt(int arg, Foo foo)
{
DoStuff(arg, foo);
return arg;
}
MyClass::MyClass(int arg, Foo foo)
: Base(DoStuffBeforeCtorAndForwardInt(arg, foo))
{
// ...
}
If you want to default-initialize the base class, you could use the copy-ctor to copy a default initialized base class instance:
Base DoStuffBeforeCtorAndReturnDefaultBase(int arg, Foo foo)
{
DoStuff(arg, foo);
return Base();
}
MyClass::MyClass(int arg, Foo foo)
: Base(DoStuffBeforeCtorAndReturnDefaultBase(arg, foo))
{
// ...
}
Or, if Base doesn't have to be the first base class, you could derive MyClass from a helper class:
MyClass::MyClass(/* ... */)
: DoStuffHelperClass(/* ... */),
Base(/* ... */)
{
// ...
}
All of the above require that the "stuff" you do does not depend on the object that's about to be initialized (i.e. the functions can't safely be member functions and you cannot safely pass this as an argument to them either).
That means you can do some logging or similar, but then again you could also do that after the base class has been initialized.
(EDIT except with the DoStuffHelperClass solution, you can of course have members in DoStuffHelperClass, access them and what not)
Although I have to say that I can't recall ever using/needing/wanting something like that. It's quite probable that there is another (preferable) solution for what you're trying to do.
Use the base-from-member idiom to run your code before the ctor of the "real" base class (which is Base):
struct Base {
Base(string, int);
};
struct DerivedDetail {
DerivedDetail() {
value = compute_some_value();
value += more();
value += etc();
other = even_more_code(value);
}
string value;
int other;
};
struct Derived : private DerivedDetail, Base {
Derived() : Base(value, other) {}
// In particular, note you can still use this->value and just
// ignore that it is from a base, yet this->value is still private
// within Derived.
};
This works even if you don't have actual members you want in DerivedDetail. If you give more specifics on what you must do before the Base's ctor, then I can give a better example.
The base class is always fully constructed before construction of your own class begins. If you need to make a change to the state of the base class, you have to do that explicitly after it has been constructed.
Example:
MyClass::MyClass()
{
// Implicit call to Base::Base()
int result = computeSomething();
Base::setResult(result);
// ...
}
Besides the already written solutions, you can also use a static constructor function and make the contructor of MyClass private.
class QtBase{
// ...
};
class MyClass : public QtBase{
public:
// copy ctor public
MyClass(MyClass const& other);
static MyClass Create(/*args*/){
// do what needs to be done
int idata;
float fdata;
// work with idata and fdata as if they were members of MyClass
return MyClass(idata,fdata); // finally make them members
}
static MyClass* New(/*args*/){
int idata;
float fdata;
// work with idata and fdata as if they were members of MyClass
return new MyClass(idata,fdata); // finally make them members
}
private:
// ctor private
MyClass(int a_idata, float a_fdata)
: idata(a_idata)
, fdata(a_fdata)
{}
int idata;
float fdata;
};
Now you would have to create instances of MyClass either as:
MyClass obj = MyClass::Create(/*args*/);
or
MyClass* ptr = MyClass::New(/*args*/);
no, because it will not be type safe.
consider you have: a class A and a variable A.var.
now consider B inherits from A, and uses var before A was initialized. you will get a run time error! the language wants to prevent this, thus superclass constructor must be initialized first.
No, you can't do it that way, as other have described in their previous answers.
Your only chance is composition, IOW that MyClass uses Base class as a member field:
class MyClass {
public:
/** the methods... */
private:
Base* _base;
};
so you can initialize _base later, when you have the needed info. I don't know if this can apply to your scenario, anyway.
No. It is not possible, because the order of constructor calls is strictly defined by the standard. Base class ctor has to be executed before the derive class ctor can be executed.