Call obejct and method via variable (string) [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
First of all, I have been looking on stackoverflow for more than 1 hour, but I really don't know, how to find the specific question I'm looking for (I guess there is already some answer).
I am trying to call an object via variable (string)
example of my code:
//class itself
using namespace std
class locations {
public:
locations(int id, string name){ // constructor
this->id= id;
this->name=name;
}
int id= 0;
string name = "";
};
and new object:
locations home(1,"home");
what I want now is something like:
string obj = "home";
obj.id = 3;
or
string meth = "id";
home.meth = 3;
If you have any good links to other questions it would be helpful.
Maybe it can be accessed somehow through vectors but I don't know about it a lot

C++ is designed with strong typing and compile time checking and optimization in mind. There's no build in facilities for the kind of access that you desire.
1) Find dynamically an object:
C++ doesn't support the semantic that you expect:
string obj = "home"; // create an object of type string.
obj.id = 3; // access to member id of your object.
If it would be dynamic, the generated code would need to maintain the scope of variables (because the home object can have different meansings in different scope.
But fortunately you can easily implement an object store, in wich you register your objects and their name, with the help of a map :
map<string, locations> mystore; // store of all my location variables
mystore["home"] = locations(1,"home"); // copy a new object into the store
string obj = "home";
mystore[obj].id = 3; // access object via its name.
By the way, if locations::name is only there to give access by name, you'd no longer need it in locations, as the map links the string to the object value anyway.
2) Find dynamically a member:
C++ doesn't support your semantic at all:
string meth = "id"; // name of a member
home.meth = 3; // invalid: because meth is not a member of home
C++ doesn't support reflection that you find in java and other semi-compiled or interpreted languages. If you need something like that, you'd need to design carefully your classes to implement this by yourself. It'll be rather difficult as every member can have its own type, and C++ needs to know the type at compile time.
One way would be to combine the use of a map (to store your dynamic members) with the use of boost::variant (to store in the map objects that can have different type of values).
But it's not easy, and most of all, you'd have to manage by yourself any inheritance logic betwwen diferent classes.

This isn't how thing are done in C++, C++ is a object oriented, statically typed, value semantics language. All of these affect design, and the design you seem want just don't fit with a statically typed language. Whether this lead you to change design, or change language is up to you. That said, if you really want to map objects and methods runtime, it could be emulated something like this:
#include <iostream>
#include <string>
#include <map>
using namespace std;
struct Object;
typedef int (*funcptr)(Object*,int);
struct Object
{
map<string,funcptr> funcs;
map<string,int> data;
int call(string name,int param) { return funcs[name](this,param); }
};
map<string,Object> allObjects;
Object& get(string name) { return allObjects[name]; }
//----------------------------------------------------------------------------------
int main()
{
get("obj1").funcs["run"] = [](Object* self,int param) -> int { self->data["somename"] = param; return 0; };
get("obj1").call("run",5);
cout << get("obj1").data["somename"] << endl;
}
That said, please don't do that, change your design to something that actually is a good fit for C++'s strengths, i.e. object oriented, statically typed, value semantics.

Related

Best C++ practice for retrieving variables from config files [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
The use case is quite common: I have a few variables that should be accessible globally (by various classes) and initialized from a configuration file. I can't decide the best way to do this.
Options struct is owned by someone and passed around:
struct Opts {
int op1;
double op2;
};
int main() {
Opts o = {3, 0.5};
// Pass this around as const reference, or potentially copying
return 0;
}
Use static vars for some Options struct.
struct Opts {
inline static int op1;
inline static double op2;
};
int main() {
Opts::op1 = 3;
Opts::op2 = 0.5;
// No passing around, but use Opts::op1 instead
return 0;
}
Use static vars, but sorta differently (not really).
struct Opts {
static int op1;
static double op2;
};
int Opts::op1;
double Opts::op2;
int main() {
Opts::op1 = 3;
Opts::op2 = 0.5;
// No passing around, but use Opts::op1 instead
return 0;
}
What should I actually do here? I thought the best case would be static const vars to make sure no one changes these, but the values can only be obtained from some file (so seems like it has to be run time instead of compile time), even though they won't change at after initializing.
I could make it const refs if I don't make it static, but that just forces me to pass this around among many classes. I also wanted the class that owns these options to be different from the class that parses them. This would just be even uglier with either moving unique_ptr or copying.
Is there a way to get best of both worlds:
not having to pass things around excessively (hence the semantics of "static")
making sure that these can't be modified after initialization, at least indicating that is the case (hence the semantics of "const")?
I commonly use a singleton Class. A config object is instantiated at startup time, and it reads the content of the file. It contains "getters" which return the values to you, and it might also contain "setters" which allow those values to be changed – in which case it also rewrites the underlying file. The settings file is simply how this object "persists" itself from one run to the next.
The object is also responsible for checking the contents of the settings to ensure that they are proper. If someone edits the file incorrectly, the object is going to throw a meaningful exception. So, if it doesn't do that, you know the settings file is good. The "setters" are equally suspicious: if some other part of the program tries to store an incorrect value, the object will catch the attempt and throw an exception.

Adressing variables by variable names [duplicate]

This question already has answers here:
Iterate through Struct and Class Members [duplicate]
(6 answers)
Closed 2 years ago.
I am currently writing a ROS 2 node to pass values from a PLC through ROS to a visualization:
PLC System --> ROS --> Visualization
Since ROS should only pass on the data, I want to be able to configure the interface here with as little effort as possible. The idea, which can be implemented best with ROS, would be a config-file(.msg file), in which the designation of the variables and their type is entered. Everything else is then derived from this.
The problem I inevitably run into with this: In ROS data are passed on over so-called messages. These messages are defined via structs and are automatically generated from my config-file. To assign values to the variables from the struct, I don't want to address every single one hardcoded in the program, but rather iterate through the struct using the known names.
TLNR: Can variables be addressed with variable variable names?
I know that the whole thing sounds a bit confusing. I hope the following example will clarify what I mean:
#include <vector>
#include <string>
struct MsgFile
{
int someVariable;
int someOtherVariable;
};
using namespace std;
class Example
{
public:
vector<string> variableNames{"someVariable", "someOtherVariable"};
MsgFile message;
void WriteVariables()
{
for (auto const &varName : variableNames)
{
message."varName" = 0; //<-- pseudo code of what I'm thinking of
}
}
};
Regards
Tillman
You cannot use variable names like that. There are no variable names at runtime. If you want a mapping between names (strings) and variables, you need to add that yourself.
If your "variables" are of same type, eg int, you can use a map:
#include <vector>
#include <string>
#include <unordered_map>
using MsgFile = std::unordered_map<std::string,int>;
struct Example {
std::vector<std::string> variableNames{"someVariable", "someOtherVariable"};
MsgFile message;
void WriteVariables() {
for (auto const &varName : variableNames) {
message[varName] = 0; // add an entry { varName, 0 } to the map
// (or updates then entry for key==varName when it already existed)
}
}
};
If you only need the string representation to access it (but not for printing etc) you can consider to use an enum as key instead. At least I'd define some constants like const std::string some_variable{"some_variable"}, to avoid typos going unnoticed (perhaps the variableNames is supposed to be const (and static?)).
As far as I know there is no standard way to do this, I would choose another way to store the data ( I mean not in struct ), but if you are adamant here is an answered question:
Get list of C structure members

How to allow a program to create new objects [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Thanks so much for taking the time to look at my question!
Right now I am working with classes and objects. I am trying to write a program that stores information about visitors to a hotel. A user will input the name of the visitor and some information about them. The program will then store that information in an object and be able to calculate how much to charge for the users stay.
The problem that I am running into is that I don't know how to let the program create new objects for the visitors. For example, if Sally came in I would like to create a new object for her within the program that could store her information.
I have looked at dynamic object creation and done a fair amount of Googling on the subject but can't seem to find any answers. Here is a simplified version of what I would like to do:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class visitor {
public:
string name;
int age;
};
int main()
{
//a new person comes to the hotel, the person at the desk gives the program his/her name
//and age and it is put into a class so it can be used later.
}
If there is a better way to accomplish this I would love suggestions, I am but a fledgling programmer and it is very possible that I am approaching this incorrectly.
Thanks in advance!
You have done fine, so far.
class visitor {
public:
string name;
int age;
};
int main()
{
//a new person comes to the hotel, the person at the desk
//gives the program his/her name
//and age and it is put into a class so it can be used later.
}
Now remember how easy it is to define a integer value i, and initialize it with 0:
int i = 0;
Your class is just like "int". So name a variable declared just like int.
visitor guest1;
You should write a default ctor to initialize the contents. Note that your code has a default ctor provided by the compiler. But what it does (nothing) is not terribly useful.
And then write a non-default ctor to fill in the contents.
and so on, and so on.
How about a show method to display values.
guest1.show();
Good luck.
You need to create a constructor. This is a function that constructs visitors. We write that as follows:
class Visitor {
public:
string name;
int age;
Visitor(string name, int age) {
this->name = name;
this->age = age;
}
};
We can then create a new Visitor object (note that its usual convention to make a class name's first letter uppercase) with the following:
Visitor sally = Visitor("Sally", 22);
To allow the user to input what we want the name and age to be, you should look at another SO answer like Getting user input in C++.
EDIT: You don't need to create a constructor as the compiler will make one by default in this case, but it will be useful for you to learn by creating your own constructors for the time being, so you know what's happening.

dumb data object holds all common values c++, is this correct

So I am new to c++ and I'm writing for a scientific application.
Data needs to be read in from a few input text files.
At the moment I am storing these input variables in an object. (lets call it inputObj).
Is it right that I have to pass this "inputObj" around all my objects now. It seems like it has just become a complicated version of global variables. So I think I may be missing the point of OOP.
I have created a g++ compilable small example of my program:
#include<iostream>
class InputObj{
// this is the class that gets all the data
public:
void getInputs() {
a = 1;
b = 2;
};
int a;
int b;
};
class ExtraSolver{
//some of the work may be done in here
public:
void doSomething(InputObj* io) {
eA = io->a;
eB = io->b;
int something2 = eA+eB;
std::cout<<something2<<std::endl;
};
private:
int eA;
int eB;
};
class MainSolver{
// I have most things happening from here
public:
void start() {
//get inputs;
inputObj_ = new InputObj();
inputObj_ -> getInputs();
myA = inputObj_->a;
myB = inputObj_->b;
//do some solve:
int something = myA*myB;
//do some extrasolve
extraSolver_ = new ExtraSolver();
extraSolver_ -> doSomething(inputObj_);
};
private:
InputObj* inputObj_;
ExtraSolver* extraSolver_;
int myA;
int myB;
};
int main() {
MainSolver mainSolver;
mainSolver.start();
}
Summary of question: A lot of my objects need to use the same variables. Is my implementation the correct way of achieving this.
Don't use classes when functions will do fine.
Don't use dynamic allocation using new when automatic storage will work fine.
Here's how you could write it:
#include<iostream>
struct inputs {
int a;
int b;
};
inputs getInputs() {
return { 1, 2 };
}
void doSomething(inputs i) {
int something2 = i.a + i.b;
std::cout << something2 << std::endl;
}
int main() {
//get inputs;
inputs my_inputs = getInputs();
//do some solve:
int something = my_inputs.a * my_inputs.b;
//do some extrasolve
doSomething(my_inputs);
}
I'll recommend reading a good book: The Definitive C++ Book Guide and List
my answer would be based off your comment
"Yea I still haven't got the feel for passing objects around to each other, when it is essentially global variables im looking for "
so this 'feel for passing object' will come with practice ^^, but i think it's important to remember some of the reasons why we have OO,
the goal (in it simplified version) is to modularise your code so as increase the reuse segment of code.
you can create several InputObj without redefining or reassignig them each time
another goal is data hiding by encapsulation,
sometimes we don't want a variable to get changed by another function, and we don't want to expose those variable globally to protect their internal state.
for instance, if a and b in your InputObj where global variable declared and initialized at the beginning of your code, can you be certain that there value doesn't get changed at any given time unless you want to ? for simple program yes.. but as your program scale so does the chances of your variable to get inadvertently changed (hence some random unexpected behavior)
also there if you want the initial state of a and b to be preserved , you will have to do it yourself ( more temp global variables? )
you get more control over the flow of your code by adding level abstractions with classes/inheritances/operation overriding/polymorphisms/Abtract and interface and a bunch of other concepts that makes our life easier to build complex architectures.
now while many consider global variable to be evil, i think they are good and useful when used properly... otherwise is the best way to shoot yourself in the foot.
I hope this helped a bit to clear out that uneasy feeling for passing out objects :)
Is using your approach good or not strongly depends on situation.
If you need some high speed calculation you can't provide incapsulation methods for your InputObj class, though they are recommended, because it will strongly reduce speed of calculation.
However there are two rules that your can follow to reduce bugs:
1) Carefully using 'const' keyword every time you really don't want your object to modify:
void doSomething(InputObj * io) -> void doSomething(const InputObj * io)
2) Moving every action related with initial state of the object(in your case, as far as I can guess, your InputObj is loaded from file and thus without this file loading is useless) to constructor:
Instead of:
InputObj() { }
void getInputs(String filename) {
//reading a,b from file
};
use:
InputObj(String filename) {
//reading a,b from file
};
You are right that this way you have implemented global variables, but I would call your approach structured, and not complicated, as you encapsulate your global values in an object. This will make your program more maintainable, as global values are not spread all over the place.
You can make this even nicer by implementing the global object as a singleton (http://en.wikipedia.org/wiki/Singleton_pattern) thus ensuring there is only one global object.
Further, access the object through a static member or function. That way you don't need to pass it around as a variable, but any part of your program can easily access it.
You should be aware that a global object like this will e.g. not work well in a multithreaded application, but I understand that this not the case.
You should also be aware that there is a lot of discussions if you should use a singleton for this kind of stuff or not. Search SO or the net for "C++ singleton vs. global static object"

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

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 (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:
Objects don't call anything, code does.
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.
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;
}