I made a test code as following:
#include <iostream>
using namespace std;
#ifndef interface
#define interface struct
#endif
interface Base
{
virtual void funcBase() = 0;
};
interface Derived1 : public Base
{
virtual void funcDerived1() = 0;
};
interface Derived2 : public Base
{
virtual void funcDerived2() = 0;
};
interface DDerived : public Derived1, public Derived2
{
virtual void funcDDerived() = 0;
};
class Implementation : public DDerived
{
public:
void funcBase() { cout << "base" << endl; }
void funcDerived1() { cout << "derived1" << endl; }
void funcDerived2() { cout << "derived2" << endl; }
void funcDDerived() { cout << "dderived" << endl; }
};
int main()
{
DDerived *pObject = new Implementation;
pObject->funcBase();
return 0;
}
The reason I wrote this code is to test if the function funcBase() can be called in an instance of DDerived or not. My C++ complier (Visual Studio 2010) gave me a compile error message when I tried to compile this code. In my opinion, there is no problem in this code because it is certain that the function funcBase() will be implemented (thus overriden) in some derived class of the interface DDerived, because it is pure virtual. In other words, any pointer variable of type Implementation * should be associated with an instance of a class deriving Implentation and overriding the function funcBase().
My question is, why the compiler give me such an error message? Why the C++ syntax is defined like that; i.e., to treat this case as an error? How can I make the code runs? I want to allow multiple inheritance of interfaces. Of course, if I use "virtual public" or re-declare the function funcBase() in Implementation like
interface DDerived : public Derived1, public Derived2
{
virtual void funcBase() = 0;
virtual void funcDDerived() = 0;
};
then everything runs with no problem.
But I don't want to do that and looking for more convenient method, because virtual inheritance may degrade the performance, and re-declaration is so tedious to do if inheritance relations of classes are very complex. Is there any methods to enable multiple inheritance of interfaces in C++ other than using virtual inheritance?
As you've defined it, your object structure looks like this:
The important point here is that each instance of Implementation contains two entirely separate instances of Base. You're providing an override of Base::funcBase, but it doesn't know whether you're trying to override funcBase for the Base you inherited through Derived1, or the Base you inherited through Derived2.
Yes, the clean way to deal with this is virtual inheritance. This will change your structure so there's only one instance of Base:
This is almost undoubtedly what you really want. Yes, it got a reputation for performance problems in the days of primitive compilers and 25 MHz 486's and such. With a modern compiler and processor, you're unlikely to encounter a problem.
Another possibility would be some sort of template-based alternative, but that tends to pervade the rest of your code -- i.e., instead of passing a Base *, you write a template that will work with anything that provides functions A, B, and C, then pass (the equivalent of) Implementation as a template parameter.
The C++ language is designed in such a way that in your first approach without virtual inheritance there will be two parent copies of the method and it can't figure out which one to call.
Virtual inheritance is the C++ solution to inheriting the same function from multiple bases, so I would suggest just using that approach.
Alternately have you considered just not inheriting the same function from multiple bases? Do you really have a derived class that you need to be able to treat as Derived1 or Derived2 OR Base depending on the context?
In this case elaborating on a concrete problem rather than a contrived example may help provide a better design.
DDerived *pObject = new Implementation;
pObject->funcBase();
This creates a pointer of type DDerived to a Implementation. When you are using DDerived you really just have a pointer to an interface.
DDerived does not know about the implementation of funcBase because of the ambiguity of having funcBase being defined in both Derived1 and Derived2.
This has created a inheritance diamond which is what is really causing the problem.
http://en.wikipedia.org/wiki/Diamond_problem
I also had to check on the interface "keyword" you have in there
it's an ms-specific extension that's recognised by visual studio
I think C++ Standard 10.1.4 - 10.1.5 can help you to understand the problem in your code.
class L { public: int next; /∗ ... ∗/ };
class A : public L { /∗...∗/ };
class B : public L { /∗...∗/ };
class C : public A, public B { void f(); /∗ ... ∗/ };
10.1.4 A base class specifier that does not contain the keyword virtual,
specifies a non-virtual base class. A base class specifier that
contains the keyword virtual, specifies a virtual base class. For each
distinct occurrence of a non-virtual base class in the class lattice
of the most derived class, the most derived object (1.8) shall contain
a corresponding distinct base class subobject of that type. For each
distinct base class that is specified virtual, the most derived object
shall contain a single base class subobject of that type. [ Example:
for an object of class type C, each distinct occurrence of a
(non-virtual) base class L in the class lattice of C corresponds
one-to-one with a distinct L subobject within the object of type C.
Given the class C defined above, an object of class C will have two
subobjects of class L as shown below.
10.1.5 In such lattices, explicit qualification can be used to specify which
subobject is meant. The body of function C::f could refer to the
member next of each L subobject: void C::f() { A::next = B::next; } //
well-formed. Without the A:: or B:: qualifiers, the definition of C::f
above would be ill-formed because of ambiguity
So just add qualifiers when calling pObject->funcBase() or solve ambiguity in another way.
pObject->Derived1::funcBase();
Updated: Also very helpful reading will be 10.3 Virtual Functions of Standard.
Have a nice weekend :)
Related
Let us suppose that we have an abstract class NonEditableSuperBase from which we create another abstract class MyBase.
The first class NonEditableSuperBase has a virtual function (non pure virtual). However, I want to force that if someone creates a class that derives from MyBase, he/she must provide an implementation to the mentioned function.
Hence, my idea is to define the function as pure virtual in MyBase.
My question: Is it a bad idea given that it was just virtual in NonEditableSuperBase?
Example:
//NonEditableSuperBase.h
class NonEditableSuperBase
{
...
public:
virtual int someMethod(); //It has an implementation, suppose {return 42;}
};
//MyBase.h
class MyBase: public NonEditableSuperBase
{
public:
explicit MyBase();
virtual ~MyBase() = default;
virtual int someMethod() = 0; //I make it pure virtual
};
//MyBase.cpp
MyBase::MyBase() : NonEditableSuperBase() { }
//Now someone creates a derived class from MyBase.
class SuperDerived : public MyBase
{
public:
explicit SuperDerived();
int someMethod(); //The user must create an implementation of the function
};
Update:
As an example, in my case I want to create some derived classes from the QAbstractTableModel class of the Qt framework. To reuse some code I want to create an intermediate abstract class.
QAbstractTableModel <- MyAbstractModel <- MyModelA (or MyModelB ... etc).
However, I want to ensure that the models (MyModelA, MyModelB) re-implement some of the virtual functions of QAbstractTableModel (like the ::index() function) because some of the additional methods of MyAbstractModel requires specific implementations of the primer functions.
From ISO IEC 14882 2014:
§ 10.4 says:
5 [ Note: An abstract class can be derived from a class that is not abstract, and a pure virtual function may
override a virtual function which is not pure. —end note ]
So It's perfectly possible to do that.
Example of use case:
You can have a basic type, that is implemented as a concrete type (base class). Now, for subtypes, we might be in a need of further additional information. So, we can have an abstract intermediate object to meet our needs.
[I'm assuming that the intent was for MyBase to publicly derive from NonEditableSuperBase, which is not what the code sample in the question actually does.]
It doesn't seem inherently dangerous, but consider that a class like SuperDerived that derives from MyBase could explicitly choose to use the NonEditableSuperBase implementation.
class SuperDerived : public MyBase {
public:
using NonEditableSuperBase::someMethod;
// Or, explicitly:
// int someMethod() override { return NonEditableSuperBase::someMethod(); }
};
This satisfies the pure-virtual requirement imposed by MyBase but acts exactly as if MyBase didn't have that requirement. You've made the author of SuperDerived do something, but you haven't actually prevented them from using the ultimate base class's implementation.
Regarding the question "How to publicly inherit from a base class but make some of public methods from the base class private in the derived class?", I have a follow-up question:
I can understand that the C++ standard allows a derived class to relax access restrictions of an inherited method, but I can not think of any legitimate use case where it would make sense to impose access restrictions in the derived class.
From my understanding of the concept of inheritance, if class Derived is public class Base, then anything you can do with Base can also be done with Derived. If one does not want Derived to fulfill the interface of Base, one should not use (public) inheritance in the first place. (Indeed, when I encountered this technique in the wild in ROOT's TH2::Fill(double), is was a clear case of inheritance abuse.)
For virtual methods, access restrictions in Derived are also useless, because any user of Derived can use them by casting a Derived* into a Base*.
So, from my limited C++ newbie point of view, these restrictions are misleading (the programmer of Derived might assume that his virtual now-protected method is not called by anyone else, when in fact it might be) and also confuses [me with regard to] what public inheritance should imply.
Is there some legitimate use case I am missing?
From Herb Sutter, Guru of the Week #18:
Guideline #3: Only if derived classes need to invoke the base implementation of a virtual function, make the virtual function protected.
For detail answer, please read my comment in the code written below:
#include <iostream>
#include <typeinfo>
#include <memory>
struct Ultimate_base {
virtual ~Ultimate_base() {}
void foo() { do_foo(); }
protected:
// Make this method protected, so the derived class of this class
// can invoke this implementation
virtual void do_foo() { std::cout << "Ultimate_base::foo"; }
};
struct Our_derived : Ultimate_base {
private:
// Make this method private, so the derived class of this class
// can't invoke this implementation
void do_foo() {
Ultimate_base::do_foo();
std::cout << " Our_derived::foo";
}
};
struct Derive_from_derive : Our_derived {
private:
void do_foo() {
// You can't call below code
// vvvvvvvvvvvvvvvvvvvvvv
// Our_derived::do_foo();
std::cout << " Derive_from_derive::foo";
}
};
// This class is marked final by making its destructor private
// of course, from C++11, you have new keyword final
struct Derive_with_private_dtor : Ultimate_base {
private:
~Derive_with_private_dtor() {}
};
// You can't have below class because its destructor needs to invoke
// its direct base class destructor
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
/*
struct Derive_from_private_dtor : Derive_with_private_dtor {
};
*/
int main() {
std::unique_ptr<Ultimate_base> p = std::make_unique<Our_derived>();
p->foo();
p = std::make_unique<Derive_from_derive>();
p->foo();
p.reset(new Derive_with_private_dtor);
}
From my understanding of the concept of inheritance, if class Derived is public class Base, then anything you can do with Base can also be done with Derived.
This isn't really the concept of inheritance; this is the concept of polymorphism. In particular, this is a statement of the Liskov Substitution Principle. But inheritance can be used for various things in C++ beyond just polymorphism. In fact, anytime your base class has non-virtual methods or data members, you are using it to inject implementation or state into derived classes, not only for polymorphism. If the base class has no virtual methods and no virtual destructor, then the class shouldn't (can't) be used polymorphically. You may use a base class where neither will the base class ever be instantiated, nor will you ever use a pointer to a base. Here's an example:
template <class T>
struct Foo {
T double_this() { return 2 * static_cast<T&>(*this).data; }
T halve_this() { return 0.5 * static_cast<T&>(*this).data; }
};
What does this weird class do? Well, it can be used to inject some interface into any class with a data member called data (and an appropriate constructor):
struct Bar : Foo<Bar> {
Bar(double x) : data(x) {}
double data;
};
Now Bar has methods double and halve. This pattern is called Curiously Recurring Template Pattern (CRTP). Note that we're never going to instantiate Foo<Bar> or have a pointer to it. We just use the interface it provides, non polymorphically.
Now, suppose someone wants to use Foo, but only wants double in their interface but not halve. In this case, it's completely valid to make halve private in the derived. After all, the derived class is just some particular, non polymorphic type, that does not need to conform to any interface other than what the author wants/documents.
Note that when using CRTP, the base class will typically provide public functions, and you'll typically inherit publicly. The entire advantage of CRTP in this use case is that you can inject interface directly; if you were going to make the methods private or inherit privately you'd be better off make Foo<Bar> a member of Bar instead. So it would be more common to make something public into something private, rather than the reverse, in this particular situation.
As it is explained in The C++ programming language:
virtual void push(char c) = 0;
virtual void pop() = 0;
The word virtual means 'may be redefined later in a class derived from this one'
The =0 syntax says that some class derived from Stack must define the function.
So why =0 symbol is needed? Does it means that a derived class must define this function, and that's to say when there is no =0, some derived classes are not forced to define this method?
I'm confusing about this, need some help.
Your thoughts were right.
So why =0 symbol is needed? Does it means that a child class must
define this function, and that's to say when there is no =0, some
child classes are not forced to define this method?
Basically you can:
Make a method non-virtual
This doesn't allow any class deriving from the class that implements the method (through either public or protected) to change the method's behavior.
Make a method virtual
This allows (but doesn't enforce) any class deriving from the class that implements the method (through either public or protected) to change the behavior of the method in the base class. You don't even have to call the original base class method anymore so you can make severe changes if needed.
Make a method pure virtual ( virtual = 0 )
This enforces that any class deriving from the class that implements the method (through either public or protected) to implement some kind of behavior/body for this method. If the deriving class does not provide an implementation then this class will instantly become abstract itself. This allows to omit the behavior/body of the method in the base class and because of this it is not allowed to directly instantiate a class that has one or more pure virtual methods (abstract class).
So why =0 symbol is needed?
Consider the following:
struct foo
{
virtual void some() const { cout << "foo" << endl; }
};
struct bar : public foo
{
virtual void some() const { cout << "bar << endl; }
};
struct baz : public foo
{
}
Suppose you have a pointer foo *p pointing to some object, and you call p->some().
If p points to a bar object, it will print "bar".
If p points to a baz object, it will print "foo".
In some cases, this might not be what you want. You might want to specify that any derived class needs to override it. The =0 does that.
The purpose of an abstract class (those classes have pure virtual method, =0) is to provide an appropriate base class from which other classes can inherit. Abstract classes cannot be used to instantiate objects and serves only as an interface.
Thus, if a subclass of an abstract class needs to be instantiated, it has to implement each of the virtual functions, which means that it supports the interface declared by the abstract class.
That is the base concept for interface.
In short, it a way to be sure a derivative class will implement those methods from the base class.
So why =0 symbol is needed?
Virtual function with sequence = 0 is known as pure virtual function, (the sequence = 0 is known as pure-specifier), it makes the class an abstract class, which can't be instantiated. For the derived classes, if they want to make it possible to be instantiated, they have to implement the pure virtual function.
No objects of an abstract class can be created. Abstract types cannot be used as parameter types, as function return types, or as the type of an explicit conversion. Pointers and references to an abstract class can be declared.
For example,
class Stack {
virtual void push(char c) = 0;
};
...
Stack s; // Fail, Stack is an abstract class
and if
class Stack {
virtual void push(char c);
};
...
Stack s; // Fine, if you won't call `push()` on it.
First consider what is the reason to use virtual methods.
1.Interface(polymorphism).
Interface in C++ is a pure virtual class, which means, that all of its methods are pure virtual (like these two you've mentioned above), it has an virtual destructor and has no constructor (it's obvious, because we can't create its instances). It also shouldn't have any data.
Let's define an interface (pure abstract class in C++):
class Interface
{
public:
virtual ~Interface(){}
virtual void somePublicMethod() = 0;
};
And define the class, which is an implementation of interface:
class Implementation : public Interface
{
public:
~Implementation() override {}
void somePublicMethod() override {}
};
If you define another pure virtual method in interface:
virtual void anotherPublicMethod() = 0;
And you don't override it in implementation you will receive compilation error, when you will declare object of Implementation type, because real Implementation object must have definitions (bodies) for all derived methods.
Yo can also define default behavior of some interface's method:
void Interface::somePublicMethod()
{
//define default behavior here
}
And call it in derived class:
void Implementation::somePublicMethod()
{
Interface::somePublicMethod();
}
How interface is used in polymorphism you will read in other topics.
2."Ordinary" Inheritance.
In "ordinary" inheritance you should use virtual methods instead of pure virtual ones, because you want to have instances of both Base class and Derived class(es). Virtual methods only indicates, that they could be overridden in derived class(es).
Conclusion
In general, if you want to have an instance of any class, this class must have all methods defined (so the must have bodies and it's obvious that they mustn't be pure virtual).
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.
I am confused about the concepts of inheritance and polymorphism. I mean, what is the difference between code re-usability and function overriding? Is it impossible to reuse parent class function using inheritance concept or else is it impossible to override parent class variables using Polymorphism. There seems little difference for me.
class A
{
public:
int a;
virtual void get()
{
cout<<"welcome";
}
};
class B:public A
{
a =a+1; //why it is called code reuse
void get() //why it is called overriding
{
cout<<"hi";
}
};
My doubt is about the difference between the code reuse and function overriding.
Lets start with your example.
class A
{
public:
int a;
virtual void get()
{
cout<<"welcome";
}
};
class B:public A
{
a =a+1; //why it is called code reuse
void get() //why it is called overriding
{
cout<<"hi";
}
};
Inheritance: Here you are deriving class B from class A, this means that you can access all of its public variables and method.
a = a + 1
Here you are using variable a of class A, you are reusing the variable a in class B thereby achieving code reusability.
Polymorphism deals with how a program invokes a method depending on the things it has to perform: in your example you are overriding the method get() of class A with method get() of class B. So when you create an instance of Class B and call method get you'll get 'hi' in the console not 'welcome'
Function inheritance allows for abstraction of behaviour from a "more concrete" derived class(es) to a "more abstract" base class. (This is analogous to factoring in basic math and algebra.) In this context, more abstract simply means that less details are specified. It is expected that derived classes will extend (or add to) what is specified in the base class. For example:
class CommonBase
{
public:
int getCommonProperty(void) const { return m_commonProperty; }
void setCommonProperty(int value) { m_commonProperty = value; }
private:
int m_commonProperty;
};
class Subtype1 : public CommonBase
{
// Add more specific stuff in addition to inherited stuff here...
public:
char getProperty(void) const { return m_specificProperty1; }
private:
char m_specificProperty1;
};
class Subtype2 : public CommonBase
{
// Add more specific stuff in addition to inherited stuff here...
public:
float getProperty(void) const { return m_specificProperty2; }
private:
float m_specificProperty2;
};
Note that in the above example, getCommonProperty() and setCommonProperty(int) are inherited from the CommonBase class, and can be used in instances of objects of type Subtype1 and Subtype2. So we have inheritance here, but we don't really have polymorphism yet (as will be explained below).
You may or may not want to instantiate objects of the base class, but you can still use it to collect/specify behaviour (methods) and properties (fields) that all derived classes will inherit. So with respect to code reuse, if you have more than one type of derived class that shares some common behaviour, you can specify that behaviour only once in the base class and then "reuse" that in all derived classes without having to copy it. For example, in the above code, the specifications of getCommmonProperty() and setCommonProperty(int) can be said to be reused by each Subtype# class because the methods do not need to be rewritten for each.
Polymorphism is related, but it implies more. It basically means that you can treat objects that happen to be from different classes the same way because they all happen to be derived from (extend) a common base class. For this to be really useful, the language should support virtual inheritance. That means that the function signatures can be the same across multiple derived classes (i.e., the signature is part of the common, abstract base class), but will do different things depending on specific type of object.
So modifying the above example to add to CommonBase (but keeping Subtype1 and Subtype2 the same as before):
class CommonBase
{
public:
int getCommonProperty(void) const { return m_commonProperty; }
void setCommonProperty(int value) { m_commonProperty = value; }
virtual void doSomething(void) = 0;
virtual ~CommonBase() { }
private:
int m_commonProperty;
};
Note that doSomething() is declared here as a pure virtual function in CommonBase (which means that you can never instantiate a CommonBase object directly -- it didn't have to be this way, I just did that to keep things simple). But now, if you have a pointer to a CommonBase object, which can be either a Subtype1 or a Subtype2, you can call doSomething() on it. This will do something different depending on the type of the object. This is polymorphism.
void foo(void)
{
CommonBase * pCB = new Subtype1;
pCB->doSomething();
pCB = new Subtype2;
pCB->doSomething(); // Does something different...
}
In terms of the code sample you provided in the question, the reason get() is called "overriding" is because the behaviour specified in the B::get() version of the method takes precedence over ("overrides") the behaviour specified in the A::get() version of the method if you call get() on an instance of a B object (even if you do it via an A*, because the method was declared virtual in class A).
Finally, your other comment/question about "code reuse" there doesn't quite work as you specified it (since it's not in a method), but I hope it will be clear if you refer to what I wrote above. When you are inheriting behaviour from a common base class and you only have to write the code for that behaviour once (in the base class) and then all derived classes can use it, then that can be considered a type of "code reuse".
You can have parametric polymorphism without inheritance. In C++, this is implemented using templates. Wiki article:
http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29#Parametric_polymorphism