C++ parametrized constructor - c++

i was wondering if parametrized constructor should always have only parameters that actually initialize class' attributes. For example, in calling:
Texture background("C:\Documents\Images\background.png");
What if i don't need to store the file path?

An object constructor takes whatever parameters are necessary for returning a valid and functional object. You may allow constructors with extra parameters for syntax sugar, but at the very least, your object should be a valid one. In your case, I don't think a texture makes sense without a file used as texture, so I think removing that parameter is not recommended.
Keep in mind though that you should also aim for making your code easy to test. In that case, complex constructors can be a pain when you want to instantiate an object for testing specif methods. In the end, it is more of a decision process.

If you don't need to store the path, then don't pass it to the constructor! :)
Parametrized constructors are intended to ensure that all information is available when the object is instanciated. So pass only the information that is neccessary.
If you want to follow the RAII idiom, then pass all requered resource to the constructor and release the resources (if the object locks them, like a file or a port).

I don't think there's anything wrong with accepting a parameter which isn't directly stored in the class. Obviously if it doesn't affect the class at all, then that's just a waste of time, but you might accept something like a PRNG seed which you use to fill your class with randomised state, and have no reason to retain the seed beyond that point.
However, passing in a file path which you mean to access within the constructor is dangerous, as there could be any number of problems that come up during that process. You really don't want trouble like that in your constructor.
In avoiding potential failure cases in your constructor you end deferring things like file access until after construction. Consequently the constructor really doesn't need the information because it makes more sense to pass it to the method you use to access the file where you can handle errors more easily.

Related

Why should you declare a copy constructor?

Why is it recommended that you explicitly declare a copy constructor,even when the compiler makes a public copy constructor when you use objects as parameters , use objects as a return value or even construct an object based on another of the same class?
Copy constructor is needed when object has dynamic memory allocations.
In default c++ compiler creates copy constructor, so when you do not have pointer etc. you do not need to define copy constructor.
Why is it recommended that you explicitly declare a copy constructor,even when the compiler makes a public copy constructor
It isn't.
If you don't have special logic to perform in a copy constructor, you don't need to provide one, and doing so is just noise.
If you do, then obviously you have to write that code by providing your own copy constructor.
Some older texts might propose you declare all special member functions, even if their definitions are empty, because if you want to add meaningful definitions later you then do not change the header that contains the definition for the class. This helps to reduce rebuild times and compatibility issues with projects using your code.
But if this ever happened it would almost certainly because you modified or added some data members, so you'd have to modify the header anyway. And, frankly, such a substantial change to a class's semantics warrants a bit of a careful eye anyway. I don't see the benefit in making code as verbose as possible just for the sake of making changes that shouldn't be completely transparent, transparent.

How to "default constructor" in C++

There's a problem I've been running into lately and since I'm a self taught C++ programer I'd really like to know how professionals in the real world solve it.
Is it a good idea to write a default constructor for all classes? Aren't there certain parts of the STL that won't work if your classes don't have default constructors?
IF SO, then how does one write a default constructor that does sensible things? That is, how can I assign default values to my private members if there simply are not sensible default values? I can only think of two solutions:
Use pointers (or unique_ptrs) for each member and that way a nullptr means the field is uninitialized.
OR
Add extra fields/logic/methods to do the work of checking to see whether or not a field has been initialized and rely on that (think kind of like unique_ptr's "reset" method).
How do people solve problems like this in the real world?
If it doesn't make sense for your data type to have a default constructor, then don't write one.
(STL is long dead, but I assume you mean the standard library.) Most standard library containers work well even if the contained type doesn't have a default constructor. Some notable gotchas:
std::vector<T>::resize(n) requires T to have a default constructor. But without one, you can use erase and insert instead.
std::map<K,V>::operator[] and std::unordered_map<K,V>::operator[] require V to have a default constructor. But without one, you can use find and insert instead.
Is it a good idea to write a default constructor for all classes?
No. If there is no sensible “default value” for your type, you should not write a default constructor. Doing so would violate the principle of least surprise.
That said, many types do have a sensible default value.
the number zero (more generally: the neutral element)
the empty string
an empty list
a 0 × 0 matrix
the time-zone UTC &pm; 00:00
…
For such types, you really should define a default constructor.
Other types don't have a natural default value but have an “empty” state that can be reached by performing certain operations. It is sensible to default-construct such an object to have that state.
an I/O stream disconnected from any source / sink that fails every operation (can be reached by reaching the end of the file or encountering an I/O error)
a lock guard that doesn't hold a lock (can be reached by releasing the lock)
a smart pointer that doesn't own an object (can be reached by releasing the managed object)
…
For these types, it is a trade-off whether to define a default constructor. Doing so does no harm but makes your type slightly more complicated. If it is a public type found in a library, then it is probably worth the trouble. If you're going to implement a move constructor (and assignment operator) anyway, you can equally well define the default constructor to construct the object in a state that would be reached by moving away from it.
For other types, you just cannot define a sensible default.
a day of the week
a name for a baby
…
Do not invent an artificial “null” state for these types just to make them default-constructible. Doing so complicates the code and forces you to provide less useful class invariants as you could without that artificial state. If somebody really needs that additional state, they can easily use an optional<T> but going the other way round is not possible.
Aren't there certain parts of the STL that won't work if your classes don't have default constructors?
Yes. std::vector::resize is probably the most prominent example. But don't worry about these. If your type does not have a sensible default value, performing that operation isn't meaningful either. It's not the fault of your type. It's inherent to the nature of the concept you're trying to model.
Is it a good idea to write a default constructor for all classes?
No. Sometimes there is no sense in having default values for object.
Aren't there certain parts of the STL that won't work if your classes don't have default constructors?
There are some parts which require DefaultConstructible objects. And there are ways to circumvent it (overloads which takes a object to use instead of default constructed).

Wrapping an opengl object into a c++ class with copying

How is this usually done?
For example you might have a texture class. This would of course hold the GLuint id, and maybe other fields such as width and height. When the object needs to be copied for whatever reason, a user-defined copy constructor is needed.
Now, in the case of an opengl texture, it is possible to copy it to another texture object. But what about shader programs, or FBOs? These can't be copied so easily. How do people usually go about doing this? Should they be reference counted? Should copying be disabled on all objects? Should copying be disabled on all objects that can't be copied?
What is the best way to go about this? Thanks in advance for any answers.
For something like a texture there may actually be a point to copying it, but for a shader object much less so (in my experience). Even for objects where copying makes sense, you don't want to do it very often so you want to make it very explicit.
Either you use your wrapper class by-value (so it is something like a handle to your OpenGL entity) and it uses reference counting internally, or you consider your wrapper class instance to own the OpenGL entity and you use reference counting on your wrapper class itself (using std::shared_ptr for example).
In the latter case you could implement a copy-constructor only on those entities for which it makes sense. However, in order to avoid unintentional use I normally resort to a private constructor and a public static factory function on the entity that returns a new instance as a smart pointer, so it is not mistakenly used by-value. In that case it also makes more sense to have an explicit "Copy/Clone" member function (easier to use and it allows for polymorphism).
In the former case the copy-constructor only increments the reference count, so you will need to add some explicit member for copying where appropriate anyway.
I usually go with the latter option by the way... I'm used to passing resource-intensive objects around by smart pointers and I don't see much point in reimplementing their functionality in custom handles.

Controlling instantiation and member variables in C++

From what I understand, when you create a C++ class, you implicitly have a default no argument constructor, a default copy constructor, and a default assignment operator.
If I want to be sure that I am alerted every time an instance of my object is created, or my object is mutated (e.g. through assignment), are these the only methods/constructors I have to worry about, given I keep all of my fields private?
If everything else in your class is private, yes.
Though do keep in mind that, if other people might have their hands in this code, unexpected modification might end up occurring in the private methods as well. So you might want to keep an eye on them too.
If the data members of your class are modified by an attack or a pointer manipulation error, you won't get alerted. Not sure if that was part of the question or not.

Is there anything wrong with returning default constructed values?

Suppose I have the following code:
class some_class{};
some_class some_function()
{
return some_class();
}
This seems to work pretty well and saves me the trouble of having to declare a variable just to make a return value. But I don't think I've ever seen this in any kind of tutorial or reference. Is this a compiler-specific thing (visual C++)? Or is this doing something wrong?
No this is perfectly valid. This will also be more efficient as the compiler is actually able to optimise away the temporary.
Returning objects from a function call is the "Factory" Design Pattern, and is used extensively.
However, you will want to be careful whether you return objects, or pointers to objects. The former of these will introduce you to copy constructors / assignment operators, which can be a pain.
It is valid, but performance may not be ideal depending on how it is called.
For example:
A a;
a = fn();
and
A a = fn();
are not the same.
In the first case the default constructor is called, and then the assignment operator is invoked on a which requires a temporary variable to be constructed.
In the second case the copy constructor is used.
An intelligent enough compiler will work out what optimizations are possible. But, if the copy constructor is user supplied then I don't see how the compiler can optimize out the temporary variable. It has to invoke the copy constructor, and to do that it has to have another instance.
The difference between Rob Walker's example is called Return Value Optimisation (RVO) if you want to google for it.
Incidentally, if you want to enure your object gets returned in the most efficient manner, create the object on the heap (ie via new) using a shared_ptr and return a shared_ptr instead. The pointer gets returned and reference counts correctly.
That is perfectly reasonable C++.
This is perfectly legal C++ and any compiler should accept it. What makes you think it might be doing something wrong?
That's the best way to do it if your class is pretty lightweight - I mean that it isn't very expensive to make a copy of it.
One side effect of that method though is that it does tend to make it more likely to have temporary objects created, although that can depend on how well the compiler can optimize things.
For more heavyweight classes that you want to make sure are not copied (say for example a large bitmap image) then it is a good idea to pass stuff like that around as a reference parameter which then gets filled in, just to make absolutely sure that there won't be any temporary objects created.
Overall it can happen that simplifying syntax and making things turned more directly can have a side effect of creating more temporary objects in expressions, just something that you should keep in mind when designing the interfaces for more heavyweight objects.