Skip to main content

Class, Struct and Constructor

Must Know Prerequisites

-> 'arrow operator' :

-> arrow operator is member selection from pointer operator

If we want a value of a member variable from a struct using a pointer, then we must use -> arrow operator as shown below ↴

info

ptr->x is same as (*ptr).memberVariable

    StructName *ptr = &obj1;

cerr << (*ptr).varName << endl;
cerr << ptr->varName << endl;

Another example

struct Paw
{
int claws;
};

struct Animal
{
string name;
Paw paw; // ⚠ `paw` is of type struct `Paw`
};

int main()
{
Animal puma {"Puma", {5}};
Animal *ptr {&puma};

cout << (ptr->paw).claws << '\n';
cerr << (*ptr).paw.claws << endl; // same as obove just bit complicated to look at

cout << ptr->name << '\n';
cerr << (*ptr).name << endl; // same as obove just bit complicated to look at
}

struct

struct st
{
int a;
double b;
string x;
};

int main()
{
st hell{45, 89.0, "9"}; // prefer this✅
/* this type of initialisation is called "Initialization list" */

st hell = {45, 89.0, "9"}; // also OK

cout << hell.a << hell.b << hell.x << endl;
}
note

using one struct inside another struct

#include <iostream>

struct Employee
{
int id {};
int age {};
double wage {};
};

struct Company
{
int numberOfEmployees {};
Employee CEO {}; // Employee is a struct within the Company struct
};

int main()
{
Company myCompany{ 7, { 1, 32, 55000.0 } }; // Nested initialization list to initialize Employee
std::cout << myCompany.CEO.wage; // print the CEO's wage
}

nested structs: declaring struct inside another struct

#include <iostream>

struct Company
{
struct Employee // accessed via Company::Employee
{
int id{};
int age{};
double wage{};
};

int numberOfEmployees{};
Employee CEO{}; // Employee is a struct within the Company struct
};

int main()
{
Company myCompany{ 7, { 1, 32, 55000.0 } }; // Nested initialization list to initialize Employee
std::cout << myCompany.CEO.wage; // print the CEO's wage
}

Constructor

caution

when we see something like this: These are Constructors as discussed in below section.

Hint: only : without ? means these are constructors

class class_a {
public:
class_a() {}
class_a(string str) : m_string{ str } {}
class_a(string str, double dbl) : m_string{ str }, m_double{ dbl } {}
double m_double;
string m_string;
};

Declare Constructors

info

Short way of declaring Constructor (used in Leetcode)

Foramt:

StructName(/* Parameters or No Paramters*/) : variable(valueOfvariable) {}

StructName(/* Parameters or No Paramters*/) : variable{valueOfvariable} {}
// `{ }` curly braces are also allowed
  • NOTE:
    • no semi-colon ; after the {} at the end of line
    • use brace initialization i.e. vareName{ _valueGiven_ } or direct initialisation varName( _valueGiven_ ) : both are right -- Leetcode uses varName(..)
Example of this constructor as used by Leetcode
//  Definition for singly-linked list.
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};

common way of declaring Constructor

common way to declare default constructor
struct StructExample
{
int a;
double b;
string x;

StructExample()
{
a = 78;
b = 89.889;
x = "Common way of declaring Constructor";
}
};

Default Constructor

StructName(-NO_PARAMETERS):variables insitialised
struct StructExample
{
int a;
double b;
string x;

StructExample() : a(78), b(89.889), x("Constructor"){} /* here a(78) is called '"brace initialization"' */
};
common way to declare default constructor
struct StructExample
{
int a;
double b;
string x;

// StructExample() : a(78), b(89.889), x("Constructor"){}; /* ALTERNATIVE to this is below common way*/
StructExample()
{
a = 78;
b = 89.889;
x = "Brace Constructor";
}
};
note

If you have constructors in your class and need a default constructor that does nothing (e.g. because all your members are initialized using non-static member initialization), use StructName() = default

Another smart way of Default Constrcutor

class StructName
{
public:
// Default constructor
StructName(int n = 0, double d = 1.2) // allows us to construct a StructName(int, double), StructName(int), or StructName()
{
}
};
int main()
{
StructName s1 { 1, 2.4 }; // calls StructName(int, double)
StructName s2 { 1 }; // calls StructName(int, double)
StructName s3 {}; // calls StructName(int, double)

StructName s4 { 2.4 }; // will not compile, as there's no constructor to handle StructName(double)

return 0;
}

Parameter Constructor

StructName(_PARAMETERS_):variables insitialised
//  Definition for singly-linked list.
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};

List initialization vs Direct initialization

List initialisation varName{..} or Brace Initialisation

info
  • always use List Initialization variableName{ _valueGiven_ } for giving vlaues to the variables
  • always use use List Initialization for giving values to tuples, maps, pairs and some other data structures
  • Only use Direct Initialisation when giving values to variables inside a Constructor

List initialisation

caution

TO LEARN FROM learncpp.com

So how do we use this constructor with parameters? It's simple! We can use list or direct initialization:

Fraction fiveThirds{ 5, 3 }; // List initialization, calls Fraction(int, int)
Fraction threeQuarters(3, 4); // Direct initialization, also calls Fraction(int, int)

As always, we prefer list initialization. We'll discover reasons (templates and std::initializer_list) to use direct initialization when calling constructors later in the tutorials. There is another special constructor that might make brace initialization do StructName different, in that case we have to use direct initialization. We'll talk about these constructors later.