xSKILLby Infirals
Register

C++ for Beginners

0 of 24 notes read 0%

Reading progress is saved to your INFIRALS account. Sign in to keep this note marked as read.

this, static members, and factories

Classes and object lifetime12 min readLesson 3 of 4

3.1 The object a member function runs on

Every non-static member function has an implicit parameter: a pointer to the object it was called on, named this. Inside set_volume, this points to the object whose set_volume is running. Writing volume_ is shorthand for this->volume_.

this is useful when a parameter has the same name as a member, when a function returns the object for chaining, and when a member function passes the whole object to another function. In a const member function the type of this is a pointer to const, so the compiler blocks changes through it.

cpp
#include <iostream>

class Settings {
public:
    Settings& set_width(int width) { width_ = width; return *this; }
    Settings& set_height(int height) { height_ = height; return *this; }
    void show() const { std::cout << width_ << "x" << height_ << "\n"; }
private:
    int width_ = 80;
    int height_ = 24;
};

int main() {
    Settings settings;
    settings.set_width(120).set_height(40);
    settings.show();
    return 0;
}

Output

120x40

3.1.1 Chaining and disambiguation

A member function that returns *this by reference hands back the object it was called on. Calls can then be chained: config.set_width(80).set_height(24);. The return type is ClassName&, so each call works on the same object.

The same expression helps when a constructor parameter shadows a member. this->name = name; assigns the parameter to the member. A trailing underscore on member names avoids the shadowing in the first place, and this-> remains available for the cases where the two names must match.

cpp
#include <iostream>
#include <string>

class Player {
public:
    Player(std::string name) { this->name = name; }
    void rename(const std::string& name) { this->name = name; }
    void show() const { std::cout << name << "\n"; }
private:
    std::string name;
};

int main() {
    Player player("Ravi");
    player.rename("Mei");
    player.show();
    return 0;
}

Output

Mei

3.1.2 Static data members

A static data member belongs to the class as a whole. The class holds one copy, and it exists even when no object has been created. A count of live objects is the usual first example.

Inside the class the member is declared with static. Before C++17 you also define it once outside the class, usually in a source file: int Connection::live_ = 0;. C++17 allows inline static int live_ = 0; inside the class, which avoids the separate definition. Access it through the class name, as in Connection::live().

cpp
#include <iostream>

class Connection {
public:
    Connection() { ++live_; }
    ~Connection() { --live_; }
    static int live() { return live_; }
private:
    static int live_;
};

int Connection::live_ = 0;

int main() {
    Connection first;
    { Connection second; std::cout << "Inside: " << Connection::live() << "\n"; }
    std::cout << "After: " << Connection::live() << "\n";
    return 0;
}

Output

Inside: 2
After: 1

3.1.3 Static member functions

A static member function has no this pointer, so it cannot read or write non-static members. It can use static members, its parameters, and its locals. Call it with the class name: Token::create(21).

Static functions are a common place for factories. A factory hides the constructor, validates arguments, and returns a fully formed object. The constructor stays private, and the static function becomes the only way to create one. A new validation rule then goes into the factory and applies to every caller.

cpp
#include <iostream>

class Token {
public:
    static Token create(int seed) { return Token(seed * 2); }
    int value() const { return value_; }
private:
    explicit Token(int value) : value_(value) {}
    int value_;
};

int main() {
    Token token = Token::create(21);
    std::cout << "Token: " << token.value() << "\n";
    return 0;
}

Output

Token: 42

3.1.4 Static locals and static members

A local variable declared static inside a function is created once and keeps its value between calls. Its lifetime runs until the program ends. A static data member also lives for the whole program, and the class owns it, while a static local belongs to its function.

Both are shared state. Shared state makes tests depend on call order, so use it for counters and caches that genuinely belong to the class. Initialization of a function-local static is thread safe in C++11 and later, which is why it appears in lazy singleton code.

3.1.5 This in const member functions

A const member function treats the object as read-only. The type of this becomes const ClassName*, so a member assignment inside that function fails to compile. Calling a non-const member function from a const member function also fails, because that call would need a non-const pointer.

A const object can call only const member functions. A const reference to an object has the same restriction. This is why getters and display functions should be marked const: without the marker, they cannot be used on const objects or through const references.

3.1.6 Common mistakes

  • Forgetting static in the class declaration but using it in the out-of-class definition, or the reverse.
  • Declaring a static data member and never defining it, which produces a linker error.
  • Writing return this; when the function promises to return an object reference. The correct expression is return *this;.
  • Using a static member for data that should be per object.
  • Calling a non-static member from a static function.
  • Returning *this by value from a chaining function, which copies the object and breaks the chain.

3.1.7 Practice

  1. Add a set_label function that returns Settings& and chain it with the existing setters.
  2. Write a class with a static counter that increases in the constructor and decreases in the destructor.
  3. Add a static factory that rejects a negative argument and returns a valid object.
  4. Mark a getter as const, call it on a const object, and then try removing const to see the error.
  5. Explain why a static member function cannot use this.

Interview questions

3 questions from this note. Open one to see the answer; no account needed.

  • 01What is `this` inside a member function?

    It is a pointer to the object the function was called on. In a const member function its type is a pointer to const, so the function cannot modify the object through it.

  • 02Why does a static data member need a definition outside the class?

    The declaration inside the class only names it. Before C++17, storage is allocated by a definition in one source file, and without that definition the linker reports an undefined symbol. C++17 inline static members can carry their initializer in the class.

  • 03What can a static member function access?

    Only static members and its own parameters and locals, because it has no object and therefore no this pointer.