Yep! This is one among a few ways this technique is implemented in C++, you simply return a reference to the instance of the class (*this). Method chaining is also employed with the operator<<, where you return an ostream& so that you can keep using the << operator to put stuff on the stream.
It's part of a broader concept called "Fluent API" [1] /"Fluent Interface" [2]. I heard about it from some web dev video a few years ago (apparently it's common in javascript).
I use this idiom in my classes when I define class methods that are meant to be used to initialize the instance.
Just a few unsolicited comments on your code:
- Why not have Initialize() be part of the constructor? The point of constructors is make the initial state of your object viable without extra external steps. You can't always do this, but in this case I think you can.
- Draw() does not mutate the state of the class, so it can be marked "const". (this might technically be true, but I realize it makes it hard to do the "chaining" which was the point of this thread, so nevermind)
- You use int for mHeight/mWidth, but you use size_t for column/row. This should be more consistent.
- Your inner loop increments "row" but you expand horizontally in the inner loop, suggesting a change in column. This seems misleading to me. I think you're accidentally transposing? Or the variables are just misnamed, I'm not sure which.
But you are correct to increment the outer array with the outer loop variable, for cache performance.
Yeah that's better, imo.
I still think it's a bit strange that you print a newline every time you increment "column", since each newline would be a new row, not column. It seems like "column" should be renamed to "row" but maybe I'm just being nitpicky.
I sometimes split out the initialize and constructor, because sometimes I want to reset an object back to its default state or reconstruct it. I know there are other ways to do it, but I tend to keep it simple in a shared function that is used by the ctor but also available to the user for that purpose. So there can be reasons for doing that one.
Agreed, that's perfectly acceptable, too, and is what I actually had in mind. I just personally wouldn't make Initialize() be a public function in that case. I would imagine it being more like std::vector::clear(), which then might internally call vector::initialize() in our hypothetical.
(But now I'm once again getting caught up on naming and not the overall design, oops!)