data member pointer being shared c++

Viewed 68

I have created two classes SystemClock which is used to show current time(by creating a pointer to struct tm from ctime) and another class called CustomClock which creates a time object from hours, minutes and seconds given by user. CustomClass inherits from SystemClock and SystemClock has a display method to display time in hours:minutes:seconds format.

For some reason the tm* field in SystemClock is being shared by all objects. Because when I create a CustomClock object say c1(1,2,3) and c2(4,5,6) and call c1.display and c2.display both of them are printing 4:5:6.(see the code below for clarity)

Code:

#include <chrono>
#include <ctime>
#include <iostream>
class SystemClock {

public:
    tm* time;
    SystemClock() {
        time_t now = std::time(0);
        time = localtime(&now);
    }
    void display() {
        std::cout << "Time: "<< this->time->tm_hour << ":";
        std::cout << this->time->tm_min << ":";
        std::cout << this->time->tm_sec << std::endl;
    }
};

class CustomClock : public SystemClock {

public:
    // CustomClock():SystemClock() {}
    CustomClock(int hours, int minutes, int seconds) {
        this->set_time(hours,minutes,seconds);
    }
    CustomClock(CustomClock &c) {
        std::cout<<"inside copy constructor";
        c.display();
        this->set_time(c.time->tm_hour,c.time->tm_min,c.time->tm_sec);
    }
    void set_time(int hours, int minutes, int seconds) {
        this->time->tm_hour = hours;
        this->time->tm_min = minutes;
        this->time->tm_sec = seconds;
    }
};

int main() {
    CustomClock c1(1,2,3);
    CustomClock c2(4,5,6);
    c2.display(); //prints Time: 4:5:6
    c1.display(); //prints Time: 4:5:6 instead of 1:2:3
    CustomClock c3(c1); //prints current time instead of 1:2:3
    c3.display();
    return 0;
}

When I did the above implementation by creating a value type data member instead of a pointer type data member, it works correctly. I am not able to understand how and why is the pointer being shared by all the objects.

3 Answers

This is how you fix your code (as pointed out by Raffallo)

class SystemClock {

public:
    tm time;
    SystemClock() {
        time_t now = std::time(0);
        time = *localtime(&now);
    }
...

The pointer is sheared, because localtime method is returning pointer to the internal object.

The returned value points to an internal object...

and

The function also accesses and modifies a shared internal object...

You can read more about it on: http://www.cplusplus.com/reference/ctime/localtime/

You should use the localtime_r. This allows you to copy the internal object content into user memory.

Related