Instantiating derived types in C++ - java

Imagine I have a Base class, and two classes that derive from it, One and Two. In Java, I could have the following scenario:
Base b;
if(condition)
b = new One();
else
b = new Two();
where the object type is determined at runtime (the above objects go on the heap).
In C++, I want to be able to instantiate the object type at runtime as well - where all I know is that they both share the same Base type - but I want to keep it stack allocated, like so:
Base b;
What's the best way to do this?

What's the best way to do this?
You can't. If you declare a variable type as Base, the stack allocation for it will be suitable for holding an instance of Base but not an instance of a derived type (which might be larger, though even if it is not, you still cannot do what you ask; the runtime type of a variable in C++ is always the same as its declared type). At best, you could slice the derived instance into a Base-type variable.
The best bet is to use a pointer, optionally wrapped in a shared_ptr or unique_ptr to give you similar semantics (i.e. to have the object be automatically destroyed when it goes out of scope, assuming ownership hasn't been transferred).
Base* b = (condition) ? (Base *) new One() : new Two();
auto bptr = shared_ptr<Base>(b);
Note that what this gives you is effectively the same as the Java. The object itself is heap allocated, but the reference to it is stack allocated. Despite the syntax, a reference-type Java variable is essentially equivalent to a pointer in C++.

Take, for instance:
Derived d;
Base* b = &d;
d is on the stack (automatic memory), but polymorphism will still work on b.
If you don't have a base class pointer or reference to a derived class, polymorphism doesn't work because you no longer have a derived class. Take
Base c = Derived();
The c object isn't a Derived, but a Base, because of slicing. So, technically, polymorphism still works, it's just that you no longer have a Derived object to talk about.
Now take
Base* c = new Derived();
c just points to some place in memory, and you don't really care whether that's actually a Base or a Derived, but the call to a virtual method will be resolved dynamically.
So, it seems, unlike Java, there is no way to achieve dynamic binding without heap allocation or pointer way.

As comments said you cannot. Well, you could but that wouldn't run:
Base &b = *(condition ? (Base *)&One() : (Base *)&Two()); // BROKEN CODE DO NOT USE
(Builds using -fpermissive, but don't do this!)
since One & Two objects are temporary objects. b would be invalid as soon as you step through next line => don't do this (not sure I said it already)
The following works, but not perfect: build both objects on the stack, so OK only if you can afford it. Just choose according to condition:
One one;
Two two;
Base &b = *(condition ? (Base *)&one : (Base *)&two);
To avoid the double allocation, the closest thing I can think of in terms of usage would be to take a reference of allocated objects (still not auto variables, sorry):
Base &b = *(condition ? (Base *)new One() : (Base *)new Two());
So you can use b as Base in your code.
You still have to delete memory with
delete (&b);

In order to use inheritance in C++ you will need to define a pointer, not a static object, and then instantiate it with new keyword.
Example:
Base* b;
if(condition)
b = new One();
else
b = new Two();

Related

Is it possible to have values for class object in java, if yes how can we acquire it?

Let's say, I am initializing a class obj as follows:
<class> obj = <some value>;
Is it possible to initialize as such I mean we initialize String and primitive values like that, But I mean for any class. And how can we get them so they can be used in some method of the same class?
Yes if it is for built in types like string, int, float etc. These built in types are pass by value. Which means if you say int a = 5, 5 is copied over to memory location.
If you are asking about your class, I do not think so. Unlike C++ you cannot overload operator. Another reason why you cannot do this is objects are pass by reference, meaning
MyClass myObject = <someValue>;
<someValue> is not copied to memory where myObject lives, instead reference (address of) it is. Thus, you need to have new myObject().
One disclaimer you can do this:
MyClass objA = new MyClass();
MyClass objB = objA;
but it is still copying reference not the actual values from myObj.
OP please read this.
While I think from some aspect this question is duplicate of this, I think the levels of knowledge between OPs of these questions is so far apart that I am not going to flag it.

C++ member variable semantics

I have a rather simple question with an inkling as to what the answer is.
My generalized question:
What is actually going on when you declare a member variable, be it public or private, and for all permutations of variable types, e.g. static vs const vs regular variables?
class some_class
{
private:
static const std::string str;
public:
...
}
I have kind of realized that in C++ there is no notion of a non-variable, that is, a non-constructed variable as I was kind of taught to believe exists with languages like Java. The same may also be true in Java, however it is not the way I was taught to think of things so I'm trying to come up with the correct way to think of these non-initialized variables.
public class main {
public static void main(String[] args) {
String str; // A kind of non-variable, or non-constructed variable (refers to null).
str = new String(); // Now this variable actually refers to an object rather than null, it is a constructed variable.
}
}
Since C++ allows you to initialize member variables in the constructor through initializer lists, and I have proven to myself via use of a debugger that the variable doesn't exist before it is initialized through the initializer list (either explicitly or by default), what is, then, actually going on behind the scenes when you declare the member variable?
Tricky question -- it's ambiguous depending on perspective.
From a pseudo-machine perspective, normally adding a non-static plain old data type to a class makes that class type bigger. The compiler also figures out how to align it and relative memory offsets to address it relative to the object in the resulting machine code.
This is pseudo-machine level because at the machine level, data types don't actually exist: just raw bits and bytes, registers, instructions, things like that.
When you add a non-primitive user-defined type, this recurses and the compiler generates the instructions to access the members of the member and so on.
From a higher level, adding members to a class makes the member accessible from instances (objects) of the class. The constructor initializes those members, and the destructor destroys them (recursively triggering destructors of members that have non-trivial destructors, and likewise for constructors in the construction phase).
Yet your example is a static member. For static members, they get stored in a data segment at the machine level and the compiler generates the code to access those static members from the data segment.
Some of this might be a bit confusing. C++ shares its legacy with C which is a hardware-level language, and its static compilation and linking affects its design. So while it can go pretty high-level, a lot of its constructs are still tied to how the hardware, compiler, and linker does things, whereas in Java, the language can make some more sensible choices in favor of programmer convenience without a language design that somewhat reflects all of these things.
Yes and no.
A variable of class type in Java is really a pointer. Unlike C and C++ pointers, it doesn't support pointer arithmetic (but that's not essential to being a pointer--for example, pointers in Pascal didn't support arithmetic either).
So, when you define a variable of class type in Java: String str;, it's pretty much equivalent to defining a pointer in C++: String *str;. You can then assign a new (or existing) String object to that, as you've shown.
Now, it's certainly possible to achieve roughly the same effect in C++ by explicitly using a pointer (or reference). There are differences though. If you use a pointer, you have to explicitly dereference that pointer to get the object to which it refers. If you use a reference, you must initialize the reference--and once you do so, that reference can never refer to any object other than the one with which it was initialized.
There are also some special rules for const variables in C++. In many cases, where you're just defining a symbolic name for a value:
static const int size = 1234;
...and you never use that variable in a way that requires it to have an address (e.g., taking its address), it usually won't be assigned an address at all. In other words, the compiler will know the value you've associated with that name, but when compilation is finished, the compiler will have substituted the value anywhere you've used that name, so the variable (as such) basically disappears (though if you have the compiler generate debugging information, it'll usually retain enough to know and display its name/type correctly).
C++ does have one other case where a variable is a little like a Java "zombie" object that's been declared but not initialized. If you move from an object: object x = std::move(y);, after the move is complete the source of the move (y in this case) can be in a rather strange state where it exists, but about all you can really do with it is assign a new value to it. Just for example, in the case of a string, it might be an empty string--but it also could retain exactly the value it had before the move, or it could contain some other value (e.g., the value that the destination string held before the move).
Even that, however, is a little bit different--even though you don't know its state, it's still an object that should maintain the invariants of its class--for example, if you move from a string, and then ask for the string's length, that length should match up with what the string actually contains--if (for example) you print it out, you don't know what string will print out, but you should not get an equivalent of a NullPointerException--if it's an empty string, it just won't print anything out. If it's a non-empty string, the length of the data that's printed out should match up with what its .size() indicates, and so on.
The other obviously similar C++ type would be a pointer. An uninitialized pointer does not point to an object. The pointer itself exists though--it just doesn't refer to anything. Attempting to dereference it could give some sort of error message telling you that you've attempted to use a null pointer--but unless it has static storage duration, or you've explicitly initialized it, there's no guarantee that it'll be a null pointer either--attempting to dereference it could give a garbage value, throw an exception, or almost anything else (i.e., it's undefined behavior).

Can Objects of user defined classes in Java be created on Stack and not dynamically on Heap like they can be in C++?

Class A {
// blah blah
}
Now, whenever we need to create an instance of this class, we do:
A a = new A();
In c++ there are two ways:
1. A a(10); // Created on Stack. Assume that the constructor takes an int argument
2. A a = new A(); // Created on Heap
How do you create user defined Java objects on stack?
No it isn't. All method-local primitive types and references are put on the stack, all objects are put in the heap. No ifs and buts about it.
One reason I can think why they did is that it removes one commonly made error: you pass the stack-based object to a method that stores a reference to that object. Then the object goes out of scope, is removed from the stack, and the reference points to something undefined. Next when you want to access the "object" through the reference, you're in a world of hurt since the object is no longer there - and nobody knows what is.

Overload a C++ assignment operator to behave like Java

In Java, when you assign one object to another, the original object isn't copied, it merely clones the reference. So, for example, I'd like it to behave like this Java code:
SomeClass x = new SomeClass();
SomeClass y;
y = x; // x is not copied, y is simply a (Java) reference to x
What I'd like to do is create a C++ class that behaves the same way. The obvious choice is to overload the assignment operator, like so:
SomeClass& operator=(const SomeClass& rhs)
{
this = &rhs;
return *this;
}
Unfortunately, assigning a new location to this is not allowed; the above code won't even compile.
Does anyone know of any other way to do this?
Also, before you say anything: yes, I know this is absolutely the wrong way to implement an assignment operator. Please, indulge me anyway.
EDIT 2: To clarify, here is the C++ code that should behave as in Java:
SomeClass x = SomeClass(); // Created on stack
SomeClass y; // In C++, same as above; NOT reference or pointer
y = x; // x is not copied, y becomes a (C++) reference to x;
// original y is destroyed when stack unwinds
I DO NOT want to use pointers at all.
EDIT: I'm doing this to see if I can change the base address of a C++ object that was passed by reference to a function. If I simply assign another object to the reference variable, it automatically makes a shallow copy, and I don't want that. I want the reference parameter to reference a completely different object.
I'm doing this to see how references are implemented by the compiler. If references are syntactic sugar for dereferenced pointers, then outside the function, the base address of the argument object would NOT change. If they are aliases in the symbol table (as in PHP), then it WILL change. (So any solution using pointers is out, since that's my "control" for the test.)
Hope that makes sense.
This isn't possible. The languages just work fundamentally differently.
SomeClass x in Java is some kind of pointer or reference to a SomeClass object. It's an indirection, so that why you can have multiple ones refering to the same object.
SomeClass x in C++ literally is the object. Thus SomeClass y is literally an entirely different object. There's no indirection. And so there's no way to make one reference the other.
C++ provides pointers (SomeClass* x) and references (SomeClass& x) to take care of the times when indirection is needed. Perhaps those are what you actually want to use, although it depends on why you asked this question in the first place.
Responding to the edit:
No, you can't change the address of an object. An instance of an object will live in exactly one place for the duration of its lifetime, until it is destroyed/deallocated.
I don't think this is okay, because even you assign this to another pointer, then the current object pointed by this will be memory leaked. Java has memory collection, but C++ not.
This is a good question, through. And this is possible.
A& operator=(const A& rhs)
{
A * cthis = const_cast<A*>(this);
cthis = const_cast<A*>(&rhs);
return *cthis;
}
Edit: It is possible to change "this pointer" inside a member function. But changing "this pointer" doesn't accomplish much.
It can be done. but, with pointer indirection.
Lets say you have a class someClass
class someClass
{
someClass *someClsPtr;
public:
someClass(someClass *someClsPtrTemp):someClsPtr(someClsPtrTemp)
{
}
someClass* operator=(someClass *someClsPtrTemp)
{
this->someClsPtr = someClsPtrTemp->someClsPtr;
return this;
}
//now over load operator -> and operator *. Thats it.
};

C++ create Object accesible by . operator on heap?

this might be stupid question, but:
When I moved from ASM to C (no, I am not actually that old, I just started to love programing on MCU), I LOVED the way heap memory is used. Malloc was my friend, and I quickly became familiar with pointers. BUT...
Than I moved to OOP and Java. And actully, despite I donĀ“t like Java as a runtime, I love its language. Now, I would like to combine both, speed and memory management capabilities of C and the beauty of OOP. So I started to learn C++.
My problem is, in Java I was used to access class members and functions with . operator. In C++, I have to use somehow not so nice and easy to type -> operator.
So, my question is, is there some way you can use . operator instead of -> to access class members of object allocated on heap? Becouse, stack is limited, and the true power of OOP is in dynamic creation of objects. Remaining "differences" are OK :) . Well, maybe C++ yould allow you to define class methods inside class, but no one can have everything, right? :D Thanks.
Class &c = *c_ptr; // dereference pointer
https://isocpp.org/wiki/faq/references
Sure. Just get a reference to some object allocated on the heap (or the stack, but that's beyond scope):
Object* my_obj_ptr = SomehowGetHeapObject();
Object& my_obj = *my_obj_ptr;
...then you can use the dot operator on the reference:
my_obj.Foo();
Perhaps a pertinent question would be, why is this throwing you off?
No, that is not posssible, at least without some syntax changes. You can use (*Pointer).Function, which Pointer->Function is just a synonym for, but I think the latter is more comfirtable (that's why it exists).
EDIT: Or as the other posts say, just store the dereferenced pointer in a reference. Haven't thought about that, as the whole question is a bit strange.
In C++ there are two ways to access members of an object, depending upon how you are holding the object. If you have the object directly (or have a reference to it), you use the dot operator, .. If you have a pointer to the object, you use the pointer operator ->.
Consider:
class C;
...
// creates a new copy of "c" on stack
int f(C c) {
c.something = c.else;
}
// creates a reference to caller's "c"
int f(C& c) {
c.something = c.else;
}
// creates a pointer to caller's "c"
int f(C* p) {
c->something = c->else;
}
So, your problem is this: you have a pointer, but you don't like the pointer operator. Frankly, I don't really see this as a problem, you should just use the pointer operator until you like it. But, this is SO, so here is a solution.
Initialize a reference from your pointer, and use the reference instead:
int f(C* p) {
C& c = *p;
c.something = c.else; // update the object pointed to by 'p'
}
Or, to make it feel even more natural:
int f2(C& c) {
c.something = c.else; // updates f1's object
}
int f1() {
C* p = new C;
f2(*p);
delete p; // don't forget this step!
}

Categories

Resources