0

I have gone through the smart pointer implementation. In the below program:

#include <iostream>

using namespace std;

class Car{

public:
    void Run(){
        cout<<"Car Running..."<<"\n";
    }
};

class CarSP{

    Car * sp;

public:
    //Initialize Car pointer when Car 
    //object is createdy dynamically
    CarSP(Car * cptr):sp(cptr)
    {
    }

    // Smart pointer destructor that will de-allocate
    //The memory allocated by Car class.
    ~CarSP(){       
        printf("Deleting dynamically allocated car object\n");
        delete sp;
    }

    //Overload -> operator that will be used to 
    //call functions of class car
    Car* operator-> ()
    {    
        return sp;
    }
};


//Test
int main(){

    //Create car object and initialize to smart pointer
    CarSP ptr(new Car());
    ptr.Run();

    //Memory allocated for car will be deleted
    //Once it goes out of scope.
    return 0;
}

This program is working fine with:

CarSP ptr(new Car());
ptr->Run();

But ptr is not a pointer its object of the class CarSP Now my doubt is how -> is used for accessing Car member function with this. If i am using ptr.Run(); But its giving error,

Please help.

  • 3
    Note the `operator->` overload that returns a `Car*`. – Fred Larson Feb 23 '18 at 17:27
  • Re, "//Initialize Car pointer when Car object is createdy dynamically"; Constructors and destructors are called for objects that are allocated on the stack or, in static variables too. – Solomon Slow Feb 23 '18 at 17:34
  • According to cppreference.com, "The overload of operator -> must either return a raw pointer or return an object (by reference or by value), for which operator -> is in turn overloaded. ". So it seems it will keep calling `operator->` on whatever you return until it gets to a raw pointer. In your case `Car::Run()` is called on the instance returned by `operator->` – patatahooligan Feb 23 '18 at 17:36

2 Answers2

0

Since I cannot include a code example in a comment, I'm adding it here as an "answer", but this is not a proper answer. See patatahooligan's link to the other Stack Overflow Q&A for a detailed explanation.

Here is a contrived example for illustrative purposes:

#include <iostream>

static char const* hello = "hello";

struct Foo
{
  char const* something() const { return hello; }
};
struct Bar
{
  Foo foo;
  Foo const* operator->() const { return &foo; }
};
struct Quux
{
  Bar bar;
  Bar const& operator->() const { return bar; }
};
struct Baz
{
  Quux quux;
  Quux const& operator->() const { return quux; }
};
struct Corge
{
  Baz baz;
  Baz const& operator->() const { return baz; }
};

int main()
{
  Corge corge;

  // The -> resolves to a Foo const*, then called something() method.
  char const* s = corge->something();

  std::cout << "Result is: " << s << std::endl;
}
Eljay
  • 4,648
  • 3
  • 16
  • 27
0
ptr->Run();

so C++ defines a->b to be (*a).b if and only if a is a pointer.

In this case, ptr is not a pointer. When a is not a pointer, it defines it to be:

(ptr.operator->())->b

in this case, ptr is a class type that has an operator->. That operator-> returns a pointer to Car.

So we have

(some pointer to Car)->b

and we recursively apply the C++ rule for ->. And as a pointer to car can be ->Run()'d, it works.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524