Chapter 9 - Worked Exercises 3

Exercise 1

The keyword static when applied in different contexts yields different results.

On a Class Member

Given the following program:

#include <iostream>

struct Foo {
    static int x;
    int y; 
    
    Foo(int some_y): y(some_y) {};
};

int Foo::x = 0; 

int main() {
    Foo one = Foo(10);
    Foo two = Foo(20);
    
    std::cout << one.y << std::endl;
    std::cout << two.y << std::endl;
    
    one.x = 25;
    std::cout << one.x << std::endl;
    std::cout << two.x << std::endl;

    two.x = 50; 
    
    std::cout << one.x << std::endl;
    std::cout << two.x << std::endl;
}

What is the output of the above program? Explain your answer.

On a Local Variable

Given the following program:

#include <iostream>

int foo() {
    static int x = 0;
    return x++;
}

int main() {  
    std::cout << foo() << std::endl;
    std::cout << foo() << std::endl;
    std::cout << foo() << std::endl;
    std::cout << foo() << std::endl;
    std::cout << foo() << std::endl;
}

What is the output of the above program? Explain your answer.

On a Member Function

Which of the following programs will compile and run?

#include <iostream>

struct Foo {
    static int sum(int x, int y) {
        return x + y;
    }
};

int main() {  
    std::cout << Foo::sum(3, 2) << std::endl;
}
#include <iostream>

struct Foo {
    static int sum(int x, int y) {
        return x + y;
    }
};

int main() {  
    Foo foo;
    std::cout << foo.sum(3, 2) << std::endl;
}
#include <iostream>

struct Foo {
    int sum(int x, int y) {
        return x + y;
    }
};

int main() {  
    std::cout << Foo::sum(3, 2) << std::endl;
}
#include <iostream>

struct Foo {
    int sum(int x, int y) {
        return x + y;
    }
};

int main() {  
    std::cout << Foo::sum(3, 2) << std::endl;
    Foo foo;
    std::cout << foo.sum(3, 2) << std::endl;
}
#include <iostream>

struct Foo {
    static int sum(int x, int y) {
        return x + y;
    }
};

int main() {  
    std::cout << Foo::sum(3, 2) << std::endl;
    Foo foo;
    std::cout << foo.sum(3, 2) << std::endl;
}

Exercise 2

The following program does not behave as expected:

#include <iostream>

struct Room {
   int capacity; 
   
   Room(int capacity) {
      capacity = capacity;
   }
};

int main() {
   Room room(25);
   std::cout << "The room's capacity is " << room.capacity << std::endl;
}

There are two ways to address this, without changing the name of the capacity parameter of the constructor, or the identically named member variable, what are they?

Exercise 3

  1. What does invoking sizeof() on a class return?

  2. Is this affected by the number of class functions defined? Does it change if these functions are static?

  3. What is word padding? Illustrate an example where word padding is applied to the composition of a class.

  4. (Bonus) Create a class that applies word padding to one or more variables. Now, show that you can reduce or increase its size simply by switching around the order of its member variables. Explain what is happening when you do this.

Exercise 4

class Burger {
    Burger(); // private constructor 
};

Burger createBurger() {
    Burger burger;
    return burger; 
}

int main() {
    Burger burger = createBurger();
}

Without changing any access modifiers of the class Burger, and only using a friend function, how can we make the above function compile?

class Burger {
    Burger(); // private constructor 
};

struct BurgerFactory {
    static Burger makeBurger();
};

int main() {
    Burger burger = BurgerFactory::makeBurger();
}

Without changing any access modifiers of the class Burger, and only using a friend class, how can we make the above function compile? (Hint, you might find this useful: https://www.geeksforgeeks.org/what-are-forward-declarations-in-c/)

Exercise 5

How much memory is taken up by the below union? Explain your answer.

union Foo {
    char a;
    int b;
    double c;
};

Part 0

You are designing a program for a smart home that's equipped with a myriad of sensors throughout the house. These sensors could provide information such as:

  • Humidity - expressed as a float (between 0 and 1 representing the percentage)

  • Temperature - expressed as an integer

  • Doorbell - expressed as a boolean indicating someone is at the door

Part 1

As you plan to add more sensors to your household in the future, you decide that a union might be a reasonable data structure to use to represent a "packet" of data sent by these sensors:

struct Packet {
    PacketData data;
    PacketType type;
    
    Packet(PacketData data, PacketType type): data(data), type(type) {}
};

Each packet has a member variable data of type PacketData, which is a union that stores the actual data of the packet as outlined in part 0.

Each packet also has a member variable type of type PacketType, which is an enum indicating the type of data that the PacketData holds.

Create the suitable definitions for the PacketData union and the PacketType enum.

Part 2

You are to create a function with the following signature:

void processPacket(Packet packet) {
  // ...
}

Which processes a packet, and prints a helpful information depending of the type of the packet:

  • The humidity is 56% right now!

  • The temperature outside is 30 degrees!

  • There is someone at the door!

  • Someone has left the door!

Below is an example of what your program might look like (it doesn't have to look exactly like this!):

int main() {
    PacketData data;
    
    data.humidity = 0.56;
    processPacket(Packet(data, PacketType::Humidity));
    
    data.temperature = 30;
    processPacket(Packet(data, PacketType::Temperature));
    
    data.door = true;
    processPacket(Packet(data, PacketType::Door));
}

Last updated

Was this helpful?