What is the C++ equivalent of java.lang.Object x = new Foo()?

后端 未结 3 1877
再見小時候
再見小時候 2020-12-10 16:21

What is the C++ equivalent of java.lang.Object x = new Foo()?

3条回答
  •  不知归路
    2020-12-10 16:30

    There is no direct equivalent to java.lang.Object x = new Foo() because in C++, not everything is an object. But depending on how you want to use these Objects, you can accomplish the same goal.

    The closest equivalent to java.lang.Object x = new Foo() in C++ is the use of Abstract Base Classes (ABC). An ABC is a class that is designed to be a base class to other classes. You create an ABC by giving your class at least one pure virtual member function, and you specify that by using this syntax:

    class Object
    {
    public:
      virtual int my_func() = 0; // The "= 0" means "pure virtual"
    };
    

    A Pure Virtual member function typically has no implementation in the base class (See footnote *1). It is not possible to create an instance of an ABC:

    int main()
    {
      Object obj; // not possible because Object is an ABC
    }
    

    In order to use an ABC, you must create a subclass of it and implement each and every pure virtual member function in the derived class:

    class Foo : public Object
    {
    public: 
      int my_func() { return 42; } // use of "virtual" is assumed here
    };
    

    Now you can create an instance of Foo, while getting a pointer to the base class:

    int main()
    {
      Object* my_obj = new Foo;
    }
    

    The usual disclaimers apply in the above code about using smart pointers etc. I omitted this for clarity, but from now on I'll use shared_ptr.

    You can also get an Object reference to Foo without having to fear slicing

    int main()
    {
      Foo my_foo;
      Object& obj_ref = my_foo; // OK
    }
    

    An important note about destructors and ABCs. When you implement an ABC, you often need to have a virtual destructor in the base class (Footnote *2). If you don't implement a virtual destructor in the base class, then when you try to delete an object through the base class pointer, you'll evoke undefined behavior, and this is bad.

       class Object
        {
        public:
          virtual int my_func() = 0;
        };
        class Foo : public Object
        {
        public: 
          int my_func() { return 42; } 
        };
    
        int main()
        {
          Object* obj = new Foo;
          delete obj;  // Undefined Behavior: Object has no virtual destructor
        }
    

    In fact, in my real-world experience in implementing ABCs I often find that the only member function that I really want to be pure virtual is the destructor. ABCs I design often have many virtual methods that are not pure and then one virtual destructor. IMO (debatable), this is a good starting point when designing an ABC: Make the dtor pure, and keep a minimal number of non-pure virtual member functions in the base class, and provide an implementation for the pure virtual dtor in the base class. As you design this way you'll find things you can't do in your actual code, and that's when you deviate from this design.


    Footnotes:


    *1 ) Base classes can provide a definition for a pure virtual member function in the base class. But this is not the norm, and the reasons you might do this are somewhat beyond the scope of this post. Note that when you do this there is a special rule in the Standard that says you may not provide the definition along with the declaration; they must be seperate. Like this:

    class Object
    {
    public:
      virtual int my_funky_method() = 0;
      virtual bool is_this_ok() = 0 { return false; } // ERROR: Defn not allowed here
    };
    
    int Object::my_funky_method()
    {
      return 43;
    }
    

    *2) There are exceptions to the rule about having virtual destructors. Beyond the scope of this article, but a better rule of thumb is "A base class destructor should be either public and virtual, or protected and nonvirtual"

提交回复
热议问题