开发者

How a member func can know *programmatically* the 'name of the object' that is calling it?

开发者 https://www.devze.com 2022-12-31 18:52 出处:网络
Let say we have a class MyClass that has and a memberfunc(). An object is created for this MyClass, say ObjA.

Let say we have a class MyClass that has and a memberfunc(). An object is created for this MyClass, say ObjA.

i.e MyClass ObjA;

ObjA calls memberfunc().

Can we get this name 'ObjA' inside memberfunc() programatically?

Note: I know how to get the type of the object, i.e 'MyClass', using RTTI (开发者_JS百科Run-Time Type Identification), the same is also explained by radman below.

EDIT:

If this is NOT POSSIBLE in c++, Is it possible in any other programming language?

EDIT2

Made some modification to the question as few were unable to interpret.


There are several issues here:

  1. Objects don't call anything, code does.
  2. Objects don't have a name. An object is usually assigned to a variable, often to more than one variable, often to no variable at all, such as an array element.
  3. Getting access to the call stack might give you some idea of the calling class that owns the code that called you, but even this usually requires a level of introspection that goes beyond the reflection facilities of most languages.
    • Python is a notable exception. It can give you the stack to walk and figure out lots of interesting things. C++ won't.

I have seen C++ libraries that crack open the stack (this is very non-portable, by the way) and thus give code the ability to figure stuff out like, "Who called me?" but I haven't used that stuff for years.


No, there is no way for it. C++ has no reflection, which would might make this possible. On 2nd thought, even the reflection facilities of e.g. Java don't have this feature.

C++ is compiled directly to machine code, which does not contain any identifiers from the source code anymore. You could of course store the "variable name" in a member field (provided the object is referred to under a single name...).


No, the object name is something that only exists in your source code. Once compiled, the object reference is just a memory offset. If you want to know the variable name, you have to have a string somewhere describing it.

The facility to get a variable name in languages with introspection mechanisms (such as Reflection) is pretty limited and not at all widely available. Even in C# - the girly man language - to get a variable name you need to use a quirky C# 3.5 feature called projection and then jump through hoops to extract it. Even then, you have to program for it - it won't just be available at any point of the code.

After some thinking the question you are posing - getting the objects' name from a member function - is theoretically impossible. Consider this scenario:

class ObjA {
public:
  void memberfunc() {
    //confused??? instance1 or instance2?
  }
};

//main
ObjA instance1;
ObjA* instance2 = &instance1;
instance2->memberfunc();

In the above example we have one instance of ObjA with two variables pointing to it(and I use term pointing rather loosely here). Those variables are something completely outside of any conceivable control of the object, hence it's impossible to get at them, even if the facility to get a variable name is available.

In C# you can use anonymous classes and Reflection to get a variable name. The method of doing so is quite awkward and if you are trying to use this to demonstrate something to someone, give up now, because you will both be confused. The technique uses some features that are new to mainstream programming and include anonymous classes, projection, extension methods and Reflection.

public static class Extensions {
  public static string GetFirstPropertyName(this object obj) {
    return obj.GetType().GetProperties()[0].Name;
  }
}

public class Program {
  public static void Main() {
    int intVal = 5;
    var name = (new {intVal}).GetFirstPropertyName();
    //name=="intVal"
  }
}


Well your question seems a little bit unclear but assuming that you want to print out the name of the class in one of it's member functions it is quite possible.

What you need to use is the typeid command. This extracts a close to human readable name for a an object of class type at runtime. However you can't rely on this name being consistent across platforms i.e. the name you get may vary from platform to platform (what I got from the example code below was '4ObjA'.

#include <iostream>
#include <typeinfo>
class ObjA
{
public:
  void memberfunc()
  {
    std::cout << typeid(*this).name() << std::endl;

  }
};

int main(int argc, char **argv)
{
  ObjA obj;
  obj.memberfunc();

}


Your question isn't entirely clear - do you want to know the object the method belongs to? Or the name of the method calling the member-function? Oo something else..?

In most object-oriented languages, you can get the name of the currently class quite easily:

class Myclass(object):
    def memberfunc(self):
        print self.__class__.__name__

obja = Myclass()
obja.memberfunc() # prints Myclass

You can't sensibly get the obja identifier as a name (in almost any language), and I can't see why you would want to (in cases like this, you'd use some kind of key/value mapping)

If you want to get the name of the method that called the method, you would have to inspect the call stack, e.g in Python using the inspect method:

import inspect

class Myclass(object):
    def memberfunc(self):
        current_call = inspect.stack()[0]
        previous = inspect.stack()[1]
        print previous[3]

def somefunc():
    obja = Myclass()
    obja.memberfunc() # prints somefunc

somefunc()

I imagine this isn't as easy in other languages

Again, the cases where you would want to do such a thing are rare, usually limited to introspection-heavy things like code coverage tools and debuggers


As has been covered in other posts, there is no direct way to access the variable name identifier that you choose in code at runtime - there is simply no need for it from the machine perspective. However, in Ruby it is trivial to get at the details of the caller in terms of its structure:

class Foo
   def foo
      puts self.class
   end
end

class Bar < Foo
end

f = Foo.new
b = Bar.new

f.foo #=> Foo
b.foo #=> Bar

You can do similar in C++ with typeid, but it is not exact. For instance:

#include <iostream>
class Foo {
    public:
        void foo () { std::cout << typeid(this).name() << std::endl; }
};

int main () {
    Foo f;
    f.foo ();  // on my system returns P3Foo
    return 0;
}


This is sort of a hack, but you could use Macros to store the class identifier name. Here's what I mean:

#include <iostream>
#include <string>

#define createMyClass(x) MyClass x("x")

class MyClass{
    string _name;
    MyClass( const string& name ) : _name(name){}
    memberfunc(){
        std::cout << "Name: " << _name << std::endl;
    }
}

int main (int argc, char **argv) {
    createMyClass( ObjA );
    ObjA.memberfunc(); // prints the name
    return 0;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消