-8

I'm new to C++, but with some experience in Javascript.

In JavaScript, when I write:

var object = {};

I create an object that is "completely generic" in the sense that it has no members/features, but it can have any member we like by adding that member later.

Can I create or simulate the this kind of an object in C++?

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 8
    You may want a C++ textbook - trying to convert javascript to C++ is not efficient. Check your C++ book for the chapter on **classes**. C++ is typed; you can't have an untyped object. – MSalters Nov 26 '20 at 14:01
  • 2
    [The Definitive C++ Book Guide and List](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) – Evg Nov 26 '20 at 14:06
  • Though you can achieve something similar like the Javascript object with `std::map>`... ;-) – Scheff's Cat Nov 26 '20 at 14:14
  • C++ is very complex and extremely unforgiving if you operate based on mistaken assumptions, so I'd definitely recommend starting with one of the books mentioned above. – dandan78 Nov 26 '20 at 14:18
  • `{}` isn't a completely generic object, it's a very specific object which has nothing in it – user253751 Nov 26 '20 at 14:41
  • 1
    @MSalters: A C++ textbook will probably not tell OP what C++ _can't_ do. Also, it's not such a bad idea to convert JS code into C++. And premature optimization is the root of all evil. – einpoklum Nov 26 '20 at 14:46
  • @Scheff: 1. What if OP wants another type? 2. What if OP wants an object-within-an-object? 3. See my answer. – einpoklum Nov 26 '20 at 14:46
  • 4
    @einpoklum -- Maybe the others are warning the OP of the pitfalls of trying to turn (or translate) other aspects of C++ into JavaScript without properly learning C++, or using JavaScript as a model in writing C++ code. – PaulMcKenzie Nov 26 '20 at 15:00
  • 2
    this question is [discussed at meta](https://meta.stackoverflow.com/q/403171/839601) – gnat Nov 26 '20 at 19:53
  • @dandan78: I would argue it's less unforgiving than it used to be. The "JS-like" approach at the beginning of my answer would been rather insane to even suggest 12 years ago (although it basically feasible); now it's almost passable, though of course not a good idea. – einpoklum Nov 26 '20 at 21:53
  • 2
    The answer depends on what exactly you want to do with these objects. Please add more use cases to make this an answerable and useful question. – NoDataDumpNoContribution Nov 27 '20 at 07:53
  • To specify and give the author a hint where to go: Questions of type "Is there feature X in C++?" are less interesting (bordering too broad) questions than "Is there feature X capable of doing Y efficiently in C++?", which can be a very interesting. Please add the Y to this question. – NoDataDumpNoContribution Nov 27 '20 at 10:51

2 Answers2

4

The answer is mostly-no, you can't.. In JavaScript, Object's can be likened to a dictionary or map from keys to typed values, with both the values and their types settable at run-time.

You can create a dictionary of arbitrary-typed values in C++, using the type-erasure capability of std::any, and strings for keys. With this approach, you can write:

using generic_object = std::unordered_map<std::string, std::any>
generic_object object;
object["foo"] = 123;
object["bar"] = [](char c) -> char { return c+1; };
object["baz"] = std::vector<int>{4,5,6,7};
std::any_cast<std::vector<int>>(object["bar"])[2] = 3 + std::any_cast<int>(object["foo"]);

You can't use plain-and-simple C++ syntax on new fields in your generic object, i.e. you can't write:

using generic_object = /* whatever */;
generic_object object;
object.foo = 123;                       // Compilation errors start here!
object.bar = []() -> char { return c+1; }
object.baz = std::vector<int>{4,5,6,7};
object.baz[2] = 3 + object.foo;
std::cout << "'a' becomes " << object.bar('a') << '\n';

like you may be used to from JavaScript. Instead, it would have to be:

struct {
   int foo;
   char (*bar)(char c);
   std::vector<int> baz;
} object;
object.foo = 123;
object.bar = []() -> char { return c+1; }
object.baz = std::vector<int>{4,5,6,7};
object.baz[2] = 3 + object.foo;
std::cout << "'a' becomes " << object.bar('a') << '\n';

And that's the "statically-typed" nature of C++. Or going even further, avoiding function pointers:

struct {
   int foo { 123 };
   char bar(char c) const { return c+1; }
   std::vector<int> baz {4,5,6,7};
} object;
object.baz[2] = 3 + object.foo;
std::cout << "'a' becomes " << object.bar('a') << '\n';

Use the clearly-typed approach, rather than the "dictionary-of-any's" I described above; that one would be cumbersome, slow, and frowned upon by most people.


See also:

What is the difference between statically typed and dynamically typed languages?

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 1
    That looks like it. I think most people misunderstood what i meant when I said object – Nikas music and gaming Nov 26 '20 at 14:50
  • 1
    @Nikasmusicandgaming: You have to be more explicit in your questions. You could have described how you've seen C++ objects behave, and what you want to do with an object after creating it. Luckily, I use Javascript, so it's more obvious to me what you would do with an object after creating it empty - but if you want good answers don't rely on luck. – einpoklum Nov 26 '20 at 14:53
0

JavaScript is dynamically typed whereas C++ is statically typed.

In JavaScript, as you showed in your example, you only need to write the variable name, without adding the type. After that, you can assign a string value but also an int value or a value of any other type.

Example:

var first;
var second;

In C++, you have to declare the type of the variable with the variable.

Example:

std::string str_value;
float float_value;
int int_value;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mrcl
  • 21
  • 3