What makes something an Abstract Class in C++ [duplicate] - c++

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What is the difference between a concrete class and an abstract class?
I was coding something in Visual C++ 2008 doing an exercise in a book I am reading when I held my cursor over one of the classes and it told me it was an abstract class. Now I know it is an abstract class as that is what this exercise is about but I was curious as to what lets the Intelisense thing know that it is an abstract class.
I did a little homework and found that it may have been the fact that I have two virtual functions in this class and one of them is a pure virtual.
Is the pure virtual a dead giveaway or are there other things that would tell you you are dealing with or looking at an abstract class?

Is the pure virtual a dead giveaway
In C++, yes. Since it has no abstract keyword or equivalent, the common idiom to make a class abstract is to declare a pure virtual function in it (which prevents instantiation).*
For this same reason, in C++ there is not much difference between an interface and an abstract class - a C++ interface is simply a class containing only pure virtual functions.
*Update: Another way to prevent instantiation of a class is to declare its constructor(s) protected or private. The latter means it can't be subclassed either, but the former doesn't prevent subclassing, so in theory a protected constructor could also be a sign of an abstract class a way to force subclassing. However, I have never seen this in practice. I believe this is because an abstract class is designed to be extended, which in practice almost always means it has virtual functions. And the reason why we want it to be abstract is because some part of its implementation is not yet known, hence it is to be defined in its subclass(es). Which is exactly what a pure virtual function is meant for.

The only thing that makes a class abstract is if it has one or more unimplemented pure virtual functions, possibly derived ones.
struct A { // abstract
virtual void f() = 0;
};
struct B : public A { // abstract
};
struct C : public B { // not abstract
void f() {}
};
Note that A should also have a (probably not pure) virtual destructor.
It is also possible to implement pure virtual functions, but this is pretty rare:
struct D {
virtual void f() = 0;
};
The function has to be defined outside the class:
void D :: f() {}
but the class remains abstract.

I wouldn't say I'm an expert in C++ but I would say you've nailed it. The presence of a pure virtual method means that the class cannot be instantiated and is therefore abstract. If all of your methods are pure virtual (i.e. there is no implementation) it would be an interface and in this case you only need the header file.

Related

Can a C++ class without any pure virtual methods be considered abstract?

My understanding is that abstract classes must have one or more pure virtual methods.
Can this class be considered abstract?
class B {
protected:
B() { }
public:
virtual ~B() { }
};
Finally, is the term abstract class defined in any of the recent C++ standards?
No, such a class cannot be considered abstract because (as mentioned in the comments, excerpt from the working draft):
A class is abstract if it has at least one pure virtual function.
Unfortunately, there are cases when one cannot add a pure virtual method to a class to turn it in an abstract one and still he doesn't want users to be able to instantiate that class.
For the sake of curiosity, I'm adding this answer to mention an often unknown technique to work around the issue.
Actually, you can easily turn such a class in an abstract one, even if you don't have any virtual method to be added to it.
The basic idea is to exploit the destructor declaration to do that.
A minimal, (not) working example follows:
struct B { virtual ~B() = 0; };
// keep in mind the ODR
B::~B() { }
int main() { B b{}; }
The code above won't compile with the error:
cannot declare variable 'b' to be of abstract type 'B'
Please, note that the definition of the destructor should be placed in a .cpp file, so as not to violate the ODR.
To be honest, I haven't found any case in which this technique can be used till now. Anyway, it's worth mentioning it for future readers.
abstract classes must have one or more pure virtual methods.
Exactly, and you class don't have it.
In accordance with this, a abstract class is a type which cannot be instantiated, but can be used as a base class (note: not "by"). In C++ this can be achieved with the usage of pure virtual method.
A pure virtual method is a virtual function whose declarator has the following syntax:
class B {
virtual void foo() = 0;
}
Note: the syntax = 0 which indicates a pure virtual method. That simply means you don't have to specify an implementation for that method, and it cannot be possible to create any instance of that class (that is, a abstract class).
In conclusion your class B is not an abstract class.
Finally, is the term abstract class defined in any of the recent C++ standards?
The abstract class is a definition itself, and it's define as I've just mentioned before.
If you mean a specific defined syntax as, for example in Java (abstract class ...), then the answer is no. Again an abstract class in C++ is defined just with a class which has a pure virtual method.
No, class B can not be considered as abstract.
class A {
public:
virtual void method() = 0;
virtual ~A() = 0;
}
A is pure virtual, you cannot create object of A. You must create children class B which implements method after A.

What type of members can I add in a c++ abstract class

Hello lets say I have a abstract class that has a few pure abstract functions and I have a few classes that derive from this class and all the data from these classes eventually becomes similar, I was wondering if it would be wise or even possible to declare a vector under protected in the abstract class to collect the data so something like.
class A
{
protected:
vector <string> str;
public:
virtual function x();
virtual function y(); //etc etc
virtual ~A(){;}
};
class B : public A
{
public:
function x();
function y();
};
class C: public A
{
//similar to class B
} ;
I am having difficulty understanding how pure virtual functions work with c++, I understand polymorphism as I have done many projects with it in java. Would it even be possible to declare and use that vector since an abstract class in c++ cant be instantiated?
I was wondering if it would be wise or even possible to declare a vector under protected in the abstract class to collect the data.
Yes, lifting up data members shared among several derived types is a legitimate design choice.
What type of members can I add in a c++ abstract class?
You can add any type of members in abstract class. In general, the data members of a class should be initialized and assigned to only within the constructor and other member functions of that class. To do otherwise breaks encapsulation, thereby making maintenance and modification of the class more difficult.
I am having difficulty understanding how pure virtual functions work with c++
Specify a virtual function as pure by placing = 0 at the end of its declaration. You don't have to supply a definition for a pure virtual function.
You cannot declare an instance of an abstract base class; you can use it only as a base class when declaring other classes.
Pure virtual member functions are declared as
virtual <return-type> func(<parameters>) = 0;
They are just virtual functions and they work as any other virtual function too. Usually, they don't have or need an implementation, but you may provide one if you want.
You can add any member you want to an abstract class in C++. An abstract class is just a regular class with one or more pure virtual member functions.
I don't see any abstract classes here
You can include members of any types into abstract class
More important than what, is why.
Abstract class is not just a "class with all functions made pure virtual". It represents a certain ideology in object oriented programming. When used as interfaces, they are not supposed to contain state.

Preventing the instantiation of a class via pure virtual functions?

I'm looking at the following code in my book:
class Shape
{
public:
Shape(){}
~Shape(){}
virtual long getArea() = 0; // Pure virtual function
virtual long getPerim() = 0;
virtual void draw() = 0;
};
Now it says that these virtual functions make the class abstract (which I understand from Java), so the class cannot be instantiated.
However, it says: "a class is in abstract data type by including one or more virtual functions in the class declaration."
Would this mean if I declared a class with ONE pure virtual function:
class Shape
{
public:
Shape(){}
~Shape(){}
virtual long getArea() = 0; // Only pure virtual function
virtual long getPerim(){}
virtual void draw(){}
};
does the whole class become abstract? Because if a class has 100+ methods, it'll be tedious to write =0 for every method if I decide to make it abstract later.
Yes, a single pure virtual method is enough to make the class abstract.
Moreover, you can always make the destructor pure virtual if no other methods are suited to be pure.
Also, your destructor should probably be virtual, since you're obviously going to inherit from this class. This is mandatory if you plan on deleting objects of a derived type through a pointer to a base type.
You are correct in that one pure virtual method is enough to make the class abstract. That means you must implement the method in a derived class to instantiate an instance (of the derived class).
I have issues with your "class with 100+ methods". Usually this is a sign of very poor design.
I also have issues with your "tedious to write =0 for every method" attitude. Firstly I do not see why it is any more tedious to write =0 than it is to write {} as a default no-op implementation (and if the method returns anything, like getPerim() does, you risk undefined behaviour by not returning something). Primarily though, business logic dictates whether or not there is a default behaviour, and not the effort of writing.
Remember the Liskov substitution principle: Although one cannot have an instance of your base class, someone will have a pointer or reference to one, and call virtual methods on it without having to know what class they really have. (Incidentally Liskov was female, first name Barbara, and stated this principle sometime around 1983).
Your abstract base class should almost certainly have a virtual destructor, by the way.
Methods that will not change the state of the class should be declared const.
Marking a function pure doesn't just make the class abstract, it makes any derived class that doesn't override the function also abstract.
So, if you want to force derived classes to implement all those functions, then make them all pure. If it makes sense for a derived class to implement only getArea and not the other two, then only mark getArea pure. In this example I suspect that it doesn't make sense, since if all the derived class has added is a way to compute the area, there's still no way that the base class can compute the perimeter.
Declaring a method as pure virtual means that classes that inherit your class will have to implement that method or leave it pure virtual, in which case the derived class will also be an abstract class that cannot be instantiated.
Also, as Luchian said previously, you should always declare the destructor as virtual for every class that will be inherited.

Virtual difference syntax C++ [duplicate]

This question already has answers here:
Virtual/pure virtual explained
(12 answers)
Closed 8 years ago.
With C++, virtual is used like this? What's the difference between the both?
class Animal
{
public:
virtual void something();
virtual void something() = 0;
}
I might be fuzzy on this but I think the first says: You can override me, and the second says, You must override me.
virtual void something() = 0; // says it is a pure virtual function
virtual void something(); // is a virtual function
And classes that contain atleast one pure virtual function are called abstract base classes.The main difference between an abstract base class and a regular polymorphic class is that because in abstract base classes at least one of its members lacks implementation, we cannot create instances (objects) of it.
The first states that the function is virtual: that subclasses can override the behaviour. However, the function still has an implementation in the base class. The second is pure virtual: it doesn't have an implementation, and must be overridden by a subclass. It's similar to the abstract keyword in Java and C#. It makes the class abstract too, so it cannot be instantiated.
The second "something" must be implemented by subclasses and any class containing "xxx() = 0" cannot be directly instantiated. It's called a "pure virtual" function and classes containing them are "abstract". A class containing nothing but pure virtuals is "pure abstract".
first one is just declaring a virtual method. if you extend the class and override that method then the child class' implementation is called.
2nd one is a pure virtual method. in other words neither your class or any class that extends it be instantiated (abstract) without first providing a definition for something().
Consider:
class Sloth : public Animal { void something() { ... } };
Animal animal;
Sloth sloth;
Here, we're trying to create two objects - an Animal and a Sloth. But, should we be allowed to create an animal? Perhaps the programmer has created Animal just so it can be used to refer polymorphically to derived types, as in:
std::vector<Animal*> zoo;
zoo.push_back(new Sloth());
zoo.push_back(new Sea_Eagle());
They might then expect p_animal->something() to do something useful. Given Animal is only inteded for this polymorphic abstraction, it would be wrong for anyone to put an actual "new Animal()" object directly into the zoo (or operate on one anywhere else in the program).
Say it was possible - what should then happen if a programmer using this Animal class creates an instance and calls the something() function? Perhaps nothing, or perhaps it's an error condition and should never appear in good code - rather than having Animal's something() function print an error message or throws an exception at run time. That's ugly - run-time errors mean the program is failing when the client's trying to use it.
C++ supports the "= 0" notation so that the compiler knows to prevent (base-class) Animal objects being created at compile time, so you can ship software that always works for the user.

Is there a way to "delete" a pure virtual function?

I have an abstract class with a couple pure virtual functions, and one of the classes I derive from it does not use one of the pure virtual functions:
class derivative: public base
{
public:
int somevariable;
void somefunction();
};
anyways, when I try to compile it, I get an error (apparently, a class is still considered abstract if derive from an abstract class and don't override all pure virtual functions). Anyways, it seems pointless to define a function
int purevirtfunc(){return 0;}
just because it needs to be defined through a technicality. Is there anyway to derive a class from an abstract class and not use one of the abstract class's pure virtual functions?
If your derived class doesn't "use" the base class pure virtual function, then either the derived class should not be derived from the base, or the PVF should not be there. In either case, your design is at fault and needs to be re-thought.
And no, there is no way of deleting a PVF.
A pure virtual class is an interface, one which your code will expect to be fulfilled. What would happen if you implemented that interface and didn't implement one of the methods? How would the code calling your interface know that you didn't implement the method?
Your options are:
Implement the method as you describe (making it private would indicate that it shouldn't be used).
Change your class hierarchy to take into consideration the design change.
The purpose of deriving from abstract classes is that external code can use the abstract class and expect that all functions have been implemented properly. Being able to unimplement a method would defeat this purpose, making the code uncompilable. You're free to throw an exception, if you so choose, however.
It's not a technicality at all. If your derived class does not exhibit all of the behavior of the parent, it should not be derived from the parent. This is a major design smell, and you probably need some design refactoring.
When you inherit from a class that has pure virtual functions, you MUST implement those functions. If you don't, then your derived class is also abstract, and you can't create an object of the derived class.
No. Either provide a default implementation in the base class or a simple implementation in the derived class, as you suggested.
There were already good answers, but if you want more info from the theoretical OO design side, check out the Liskov substitution principle.
Allowing this wouldn't make any sense. What would happen if you called the function without an implementation? A runtime error (that would be silly)? You could argue that it could a compile time error in some cases, but this is not possible if the exact type is not known (e.i. you pass a pointer to an instance of the derived class to a function).
As many people have already stated, it sounds like either the base method shouldn't be pure virtual or you should rethink whether your derived class really ISA base.
However, it is possible to provide an implementation for the pure virtual method in the base class. This can act like a default implementation for derived classes, but you still require the derived class to choose the base class's implementation explicity.
I don't know if that will help you with your problem or not.
No, there isn't. The convention in late bound languages when this situation occurs (as it legitimately might, but consider your design to see whether this method can be moved elsewhere, perhaps to its abstract class), is to raise an exception, and make sure that users of that method know that some implementations may raise that exception.
Seems i faced with the same problem, when trying to hide method getVertex() in derived class.
Maybe it's help.
class Body2D
{
public:
virtual ~Body2D() = default;
virtual double getCenter() const = 0;
virtual double getVertex() const = 0;
};
class Ellipse : public Body2D
{
public:
Ellipse(){};
double getCenter() const override{};
private:
double getVertex() const override{};
};
Couldn't you just do
class Foo {
public:
virtual void foo() = 0;
};
class Bar {
public:
virtual void foo() = delete;
};