Why do not C++ object methods expect a self argument unlike python?

1.1k views Asked by At

After a bit of experimentation I discovered something curious in Python (possibly obvious to experts, forgive me in that case). That is, a python class method can be invoked with two different syntax as opposed to C++. I will give two minimum working examples with a simple class which just contains an integer attribute and can add another integer to it. First the C++.

#include <iostream>
using namespace std;
class MyClass
{
    int value;
    public:
    MyClass(int arg){value=arg;}
    int add(int arg){return arg+value;}
};

int main()
{
    MyClass anObject(4);
    cout<<"The addition gives "<<anObject.add(6)<<endl;//Outputs 10

    //cout<<"The alternative way to call the method gives "<<MyClass.add(anObject, 6)<<endl;  //Does not work

   //cout<<"Another alternative way to call the method gives "<<MyClass::add(anObject, 6)<<endl;  //Does not work either

   return EXIT_SUCCESS;
}

and the python.

class MyClass(object):
    def __init__(self, arg=3):self.value=arg
    def add(self, arg):return arg+self.value
anObject=MyClass(4)
print(anObject.add(6)) #The C++ way, Outputs 10
print(MyClass.add(anObject, 6))  #Outputs 10

Obviously, this is not a problem that I am trying to solve, but the objective of this question is to see a discussion around why option 2 is made a feature for python while it is not one in C++? Does it follow from some deeper design philosophy of the languages, or something to do with the compiled vs interpreted nature of the languages? Related, why is self presented as a dummy argument in python but not in C++?

1

There are 1 answers

3
Yakk - Adam Nevraumont On

Python classes are runtime objects. Each object carries with it a __class__ pointer.

When you do obj.foo(x) it looks first locally for a foo method; if it fails to find it, it invokes obj.__class__.foo(obj, x).

In C++ classes are not runtime objects. An object with virtual methods or inheritance has a vtable, but the vtable is not the class, but rather a way to get at minimal & efficient type and dispatching information for methods.

Now you can still invoke a C++ method in a way like a python one:

template<class T>
T& as_lvalue(T&&t){return t;}

std::ref( as_lvalue(&MyClass::add) )( anObject, 6 );

this uses the INVOKE concept (post you can use it directly with std invoke) and a member function pointer.

This is a library solution. There is no MyClass object in the executable at runtime.