C ++ and Java Constructors

According to John S. Mitchell - concepts in programming languages,

[...] Java ensures that the constructor is called whenever an object is created. [...]

This is indicated as a feature of Java that distinguishes it from C ++ in its behavior. Therefore, I must argue that C ++ in some cases does not call the constructor for the class, even if an object for this class is created.

I think this happens when inheritance happens, but I cannot find an example for this case.

Do you know any example?

+6
java c ++ inheritance programming-languages
source share
15 answers

Giving an interpretation, I have an assumption about why the author says that for Java, without looking at any corner cases that I think do not really affect the problem: you might think, for example, that PODs are not objects .

The fact that C ++ has unsafe types is much better known. For example, using a simple mixture of C and C ++, you can do this:

class A { int x; public: A() : X(0) {} virtual void f() { x=x+1; } virtual int getX() { return x; } }; int main() { A *a = (A *)malloc(sizeof(A)); cout << a->getX(); free(a); } 

This is a perfectly acceptable C ++ program and uses an unverified cast form to avoid calling the constructor. In this case, x is not initialized, so we can expect unpredictable behavior.

However, there may be other cases in which Java also does not apply this rule, mentioning a serialized object is perfectly reasonable and correct, even if you know for sure that the object has already been constructed in some way (unless you crack some serialized encoding, of course )

+1
source share

If your class defines at least one constructor, then the language will not allow you to build an object of this type without calling the constructor.

If your class does not define a constructor, the general rule is that the default constructor created by the compiler will be called.

As other posters noted, if your class is a POD type, there are times when your object will remain uninitialized. But this is not because the compiler "did not call the constructor." This is because the type does not have a constructor (or it has one that does nothing), and it is handled somewhat specially. But then again, POD types do not exist in Java, so they cannot be compared.

You can also hack everything so that the constructor is not called. For example, select char 's buffer, take a pointer to the first char and apply it to the type of the object. Undefined behavior in most cases, of course, so it really is not allowed, but the compiler will not complain at all.

But the bottom line is that any book that makes such claims without much clarity regarding the specific cases that they mean is likely to be filled with garbage. On the other hand, most people writing about C ++ know little about the language, so this should not be a surprise.

+14
source share

There are two cases in Java (I don’t know anything else) in which a class can be constructed without calling its constructor, without leading to hacking in C or similar:

  • Serializable classes do not have a constructor during deserialization. The no-arg constructor of the most derived non-serializable class is called by the serialization mechanism (in the Sun implementation through non-validated bytecode).
  • When using evil Object.clone .

Thus, the statement that constructors are always invoked in Java is false.

+9
source share

For C ++ types declaring constructors, it is not possible to instantiate these types without using a constructor. For example:

 class A { public: A( int x ) : n( x ) {} private: int n; }; 

it is impossible to create an instance from A without using the constructor A (int), except by copying, which in this case will use the synthesized copy constructor. In any case, the constructor should be used.

+4
source share

Java constructors may call another constructor of the same class. In C ++, this is not possible. http://www.parashift.com/c++-faq-lite/ctors.html

PODs (plain old data types) are not initialized via constructors in C ++:

 struct SimpleClass { int m_nNumber; double m_fAnother; }; SimpleClass simpleobj = { 0 }; SimpleClass simpleobj2 = { 1, 0.5 }; 

In both cases, the constructor is not called, not even the default constructor is created:

If, however, SimpleClass defined the constructor itself, SimpleClass will no longer have a POD, and one of the constructors will always be called.

+3
source share

In C ++, when an instance of an object is created, you must call the constructor of this class.

+2
source share

In C ++, there are special cases where the constructor will not be called. In particular, for POD types, an implicit default constructor will not be called in some situations.

 struct X { int x; }; int main() { X x; // implicit default constructor not called // No guarantee in the value of xx X x1 = X(); // creates a temporary, calls its default constructor // and copies that into x1. x1.x is guaranteed to be 0 } 

I don’t quite remember the whole set of situations when this can happen, but I seem to remember that this was mainly in this case.

To further solve the problem:

This is indicated as a feature of Java that distinguishes it from C ++ in its behavior. Therefore, I must argue that C ++ in some cases does not call the constructor for the class, even if an object for this class is created.

Yes, with POD types you can create objects and the constructor will not be called. And the reason is because

This, of course, is for compatibility with C.

(as Neil notes)

I think this happens when inheritance happens, but I cannot find an example for this case.

This has nothing to do with inheritance, but with the type of object being created.

+2
source share

Java can actually allocate objects without (!) Calling any constructor.

If you look at ObjectInputStream sources, you will find that it selects deserialized objects without calling any constructor.

The method that allows you to do this is not part of the open API, it is in the sun.* package sun.* . However, please do not tell me that because of this, it is not part of the language. What you can do with the public API is to combine the byte stream of the deserialized object, read it, and go where you go with the object instance whose constructor has never been called!

+2
source share

Only when you overload a new operator function, the constructor is not called (it is used to exclude the constructor call), otherwise the constructor calls it in the standard when creating the object.

 void * operator new ( size_t size ) { void *p = malloc(size); if(p) return p; else cout<<endl<<"mem alloc failed"; } class X { int X; }; int main() { X *pX; pX = reinterpret_cast<X *>(operator new(sizeof(X)*5)); // no ctor called } 
+1
source share

As far as I remember, Meyers in his Effective C ++ says that the object is ONLY created when the control flow reaches its end of the constructor. Otherwise, it is not an object. Whenever you want to mess up some raw memory for a real object, you can do this:

 class SomeClass { int Foo, int Bar; }; SomeClass* createButNotConstruct() { char * ptrMem = new char[ sizeof(SomeClass) ]; return reinterpret_cast<SomeClass*>(ptrMem); } 

You won’t click any constructors here, but you might think that you are working with a newly created object (and debugging it perfectly),

0
source share

An attempt to clarify the situation in C ++. Many inaccurate statements in the answers.

In C ++, POD and class behave the same. The constructor is ALWAYS called. For POD, the default constructor does nothing: it does not initialize the value. But the error is that the constructor is not being called.

Even with inheritance, constructors are called.

 class A { public: A() {} }; class B: public A { public: B() {} // Even if not explicitely stated, class A constructor WILL be called! }; 
0
source share

This is similar to the definition of the term “object,” so the statement is a tautology. In particular, with respect to Java, it seems to define an “object” to denote an instance of a class. As for C ++, it (apparently) uses a wider definition of an object, which includes things like primitive types that don't even have constructors.

Regardless of its definitions, however, C ++ and Java are much more alike than different in this respect. Both have primitive types that don't even have constructors. Both support the creation of custom types, which guarantee the invocation of constructors when creating objects.

C ++ also supports the creation (within very defined limits) of user-defined types that do not necessarily have constructors called under all possible circumstances. However, there are strict restrictions on this. One of them is that the constructor must be "trivial", i.e. It should be a constructor that does nothing that was automatically synthesized by the compiler.

In other words, if you write a class with a constructor, then the compiler can use it at the right time (for example, if you write a copy constructor, all copies will be made using your copy constructor). If you write a default constructor, the compiler will use it to create all objects of this type for which an initializer is not specified, etc.

0
source share

even when we use a statically allocated memory buffer to create an object, the constructor is called.

can be seen in the following code snippet. I have not seen any general case where the constructor is not called, but then you can see so much :)

turn on

using the std namespace;

class Object

{

public:

An object();

~ Object ();

};

inline Object :: Object ()

{

cout <"Constructor \ n";

};

inline Object :: ~ Object ()

{

cout <"Destructor \ n";

};

int main ()

{

char buffer [2 * sizeof (Object)];

Object * obj = new (buffer) Object; // placement of a new, 1st object

new (buffer + sizeof (Object)) Object; // placement of a new, second object

// remove obj; // DO NOT DO IT

.

OBJ [0] ~ Object (); // destroy the 1st object

.

OBJ [1] ~ Object (); // destroy the second object

}

0
source share

There are situations in Java when the constructor is not called.

For example, if a class is deserialized, the default constructor of the first non-serializable class in the type hierarchy will be called, but not the constructor of the current class. Object.clone also avoids calling the constructor. You can also generate bytecode and do it yourself.

To understand how this is possible, even without the built-in code magic inside the JRE, just take a look at the Java bytecode. When the new keyword is used in Java code, two bytecode instructions are generated from it - first, the instance is assigned by the new instruction, and then the constructor is called with the invokespecial instruction.

If you create your own bytecode (for example, with ASM), it is possible to modify the invokespecial command to invoke the constructor of one of the real-type superclass constructors (for example, java.lang.Object ) or even skip the constructor call completely. The JVM will not complain about it. (Bytecode verification verifies that each constructor calls its own superclass constructor, but the calling constructor object does not check which constructor is called after new .)

You can also use the Objenesis library, so you do not need to generate bytecode manually.

0
source share

What he means in Java is always called a superclass constructor. This is done by calling super (...), and if you omit this compiler, it will insert one for you. The only exception is that one constructor calls another constructor. In this case, another constructor should call super (...).

This automatic code insertion by the compiler is actually weird. And if you do not have a super (...) call, and the parent class does not have a constructor without a parameter, this will lead to a compilation error. (It is odd to have a compilation error for what is automatically inserted.)

C ++ will not do this automatic insert for you.

-one
source share

All Articles