C++ vs Java constructors

前端 未结 14 2459
一个人的身影
一个人的身影 2021-02-09 20:31

According to John C. Mitchell - Concepts in programming languages,

[...] Java guarantees that a constructor is called whenever an object is created.

相关标签:
14条回答
  • 2021-02-09 21:26

    This seems comes down to defining the term "object" so that the statement is a tautology. Specifically, with respect to Java, he's apparently defining "object" to mean an instance of a class. With respect to C++, he (apparently) uses a broader definition of object, that includes things like primitive types that don't even have constructors.

    Regardless of his 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 creation of user defined types that guarantee the invocation of constructors when objects are created.

    C++ does also support creation (within very specific limits) of user defined types that don't necessarily have constructors invoked under all possible circumstances. There are tight restrictions on this, however. One of them is that the constructor must be "trivial" -- i.e. it must be a constructor that does nothing that was automatically synthesized by the compiler.

    In other words, if you write a class with a constructor, the compiler is guaranteed to use it at the right times (e.g. 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 make all objects of that type for which no initializer is supplied, and so on.

    0 讨论(0)
  • 2021-02-09 21:27

    There are two cases in Java (I'm not aware of any more) in which a class' may be constructed without its constructor being called, without resulting to hacking in C or similar:

    • During deserialisation, serialisable classes do not have their constructor called. The no-arg constructor of the most derived non-serialisable class is invoked by the serialisation mechanism (in the Sun implementation, through non-verifiable bytecode).
    • When the evil Object.clone is used.

    So the claim that constructors are always called in Java, is false.

    0 讨论(0)
  • 2021-02-09 21:29

    In C++, when an object is instantiated, a constructor of that class must be called.

    0 讨论(0)
  • 2021-02-09 21:30

    Giving an interpretation, I have a suggestion about why the author says that for Java, without looking for any corner cases which I think don't address really the problem: you could think for example that PODs are not objects.

    The fact that C++ has unsafe type casts is much more well known. For example, using a simple mixture of C and C++, you could 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 program in C++ and uses the unchecked form of type cast to avoid constructor invocation. In this case x is not initialized, so we might expect an unpredictable behaviour.

    However, there might be other cases in which also Java fails to apply this rule, the mention of serialized object is perfectly reasonable and correct, even though you know for sure that the object has already been constructed in some way (unless you do some hacking on the serialized encoding of course).

    0 讨论(0)
  • 2021-02-09 21:30

    In Java there are some situations when the constructor is not called.

    For example when 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. Also Object.clone avoids calling the constructor. You can also generate bytecode and do it yourself.

    To understand how this is possible, even without native code magic inside the JRE, just have 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 allocated with the new instruction and then the constructor is called with the invokespecial instruction.

    If you generate your own bytecode (for example with ASM), it's possible change the invokespecial instruction to call the constructor of one of the actual type's super classes' constructor (such as java.lang.Object) or even completely skip calling the constructor. The JVM will not complain about it. (The bytecode verification only checks that each constructor calls its super class's constructor, but the caller of the constructor is not checked for which constructor is called after new.)

    You can also use the Objenesis library for it, so you don't need to generate the bytecode manually.

    0 讨论(0)
  • 2021-02-09 21:32

    Only When you overload new operator function then constructor is not called (it used to avoid constructor calling), else its in standard that constructor is invoked when object is created.

    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
    
    }
    
    0 讨论(0)
提交回复
热议问题