10

I am stuck on a point at my C++ personal learning process. I come from Java language.

I am trying to set a class in C++ which have an abstract method. Up to there, there is no big deal. But I'd like to instantiate that class as I can do in Java:

// MyClass has an abstract method named "AbstractMethod"
MyClass class_object = new MyClass()
{
   @Override
   public void AbstractMethod()
   {
     // Do something here
   }
};
class_object.AbstractMethod();

In Java, it works perfectly. But i'd like to do the same in C++, and there is a problem here: C++ doesn't seems to like the idea of instantiating a class having virtual method.

I have searched for some days now and I can't find any answer to that question on internet. Maybe it is just me badly writting the search sentence, as I am not a native English speaker I might have some difficulties finding the correct syntax on asking that question.

Is there any possibility for me, in C++, to do as in Java or at least, likely? Is using Templates a solution ? (never learned templates before, I still have a lot to learn).

Also, I cannot create numerous classes to redefine a method, as this class will be used to do a custom treatment for each instance. It would be, I think, a waste to create classes just to see it being the proud father of one and only one object of that type.

user207421
  • 305,947
  • 44
  • 307
  • 483
Hugo Regibo
  • 697
  • 1
  • 9
  • 20
  • 12
    You are not instantiating an abstract class. You are instantiating a **concrete subclass** of an *abstract class* – TheLostMind Mar 23 '16 at 10:26
  • 1
    afaik, you cannot instantiate an abstract class (neither in java nor in c++). But you definitely can instantiate a class with a virtual method in c++ – 463035818_is_not_an_ai Mar 23 '16 at 10:26
  • 1
    `C++ doesn't seems to like the idea of instantiating a class having virtual method.`, make that a `pure virtual method`. – Stefan Mar 23 '16 at 10:26
  • 3
    You can not instance an abstract class _by definition_. The code you show has an _anonymous class_. – Raedwald Mar 23 '16 at 10:27
  • Read [this question first](http://stackoverflow.com/questions/2391679/why-do-we-need-virtual-methods-in-c) ;) – Shark Mar 23 '16 at 10:28
  • 1
    can you please show the c++ code that is not working? Because what you describe should be perfectly possible in c++ (well not instantiating an abstract class, but thats also not really what you show in the java example) – 463035818_is_not_an_ai Mar 23 '16 at 10:28
  • You cannot instantiate a class with a `pure virtual method`, but can always instantiate a class with a virtual method. You can create an interface class with a `pure virtual method` and force the derived class to implement the `pure virtual method` and then use a pointer to base class to point to the derived classes - basic polymorphism. You can also have your base class define a `virtual method` with a default behavior and then have your derived class override the `virtual method` if and only if needed. In this case you can instantiate base class. – Vishal Mar 23 '16 at 10:29
  • See http://stackoverflow.com/questions/30545884/c11-alternative-to-the-java-anonymous-callback-class – Raedwald Mar 23 '16 at 10:31

4 Answers4

8

I would say - in c++, the equivalent of your java code would be:

#include <iostream>

struct A {
    virtual void foo() = 0;
};

int main(void) {
    struct B : public A {
        void foo() override {
            std::cout << "inst::foo()" << std::endl;
        }
    };
    A* p = new B;
    p->foo();
}

As you can see there is no such thing as instantiating an abstract class, you must provide a concrete implementation to instantiate. The subtle difference is that in java it's an anonymous class, here it's not...

Nim
  • 33,299
  • 2
  • 62
  • 101
  • 2
    Might want to add a `delete p;` at the end of `main()`. C++ does not have garbage collection, so forgetting to release a dynamically allocated object is (at best) a poor idea and (at worst) a really bad idea in C++. – Peter Mar 23 '16 at 11:23
  • Awesome, big thanks to you all for the informations and sorry for the wrong terms that made me be misunderstood. Cheers ! – Hugo Regibo Mar 23 '16 at 14:58
  • Including the new type within the method just adds more confusion to an already difficult language. You could add the new type elsewhere to make it slightly more coherent. – Dave Doknjas Mar 23 '16 at 15:28
  • @DaveDoknjas The point of this isn't to highlight the best approach (that's subjective and debatable.) The point of this is to show the equivalent of the java code the op posted... – Nim Mar 23 '16 at 16:05
  • @Nim: Yes, it is the closest equivalent, but is also one of the worst 'features' of C++. – Dave Doknjas Mar 23 '16 at 16:15
  • Nim - it's all well and good for beginners to learn. It is not so good for people to knowingly give them deceptive examples of poor practice. Cases like this, where people need to learn by being told because symptoms of a problem are not always readily apparent, are poor teaching. – Peter Mar 24 '16 at 10:11
2

It is not an instantiation of the MyClass in your example! You just extend it with anonymous inner-class and then instantiate it's instance by this code and syntax (class isn't so much anonymous, though - under the hood it has a name like YourClass$1).

And then you can place a reference of this anonymous YourClass$1 class instance to the variable with MyClass because it is a superclass (you can use Object or some interface type too)

C++ 11 doesn't have exactly the same type of inner-classes and extend/instantiate syntax, but you can try to use Lambdas to achieve similar results. Look here: Does C++0x support Anonymous Inner Classes?

Community
  • 1
  • 1
Cootri
  • 3,806
  • 20
  • 30
0

Java, unlike c++, distinguishes between an interface and an abstract class, maybe this is the source of your confusion.

This is how an Java interface looks in c++:

class myClass{
   virtual void foo =0; //pure virtual method
}

This is an Java abstract class in c++:

class myClass{
   virtual void foo=0;
   virtual void abstractMethod(); 
}

Neither of these can be instantiated, you can only inherit from them and override the abstract methods.

class myClass_Impl: public myClass
{
   void foo();//must provide an implementation for pure virtual methods
   void abstractMethod(); //override the abstract class method
}

main()
{
   myClass_Impl x; //instace of your class
   myClass * p = new myClass_Impl(); //using polymorphism 
}
Pandrei
  • 4,843
  • 3
  • 27
  • 44
0

The syntax is a little different. But you can return instances of local classes:

class MyAbstractClass {
public:
    virtual void my_method() = 0;
};

MyAbstractClass* some_function() {
    class MyConcreteClass : public MyAbstractClass { // Our local class definition.
    public:
        virtual void my_method() override {
            // some code
        }
    };

    return new MyConcreteClass(); // Return a pointer to an instance of it
}
Jorn Vernee
  • 31,735
  • 4
  • 76
  • 93
  • That is not returning an instance of `MyAbstractClass` though. It is returning a pointer which points at an instance of a derived class, which is a different thing. – Peter Mar 23 '16 at 11:06
  • About the same thing happens in java. And like I said "return instances of local classes" or pointer to in this case. – Jorn Vernee Mar 23 '16 at 11:19