I was wondering how can one explain this mechanism:
class Base{
class Other;
virtual void test() = 0;
};
class Other: Base{
virtual void test() override;
};
void Other::test(){ /*do something*/}
It looks like I have a base class called Base. It contains of a nested class which inherits from the Base. So if I call:
Base obj;
obj.test(); <-- it trigers the test() function from the Other class, doesn't it?
What is the difference between the given example and the following:
class Base{
virtual void test() = 0;
};
class Other: Base{
virtual void test() override;
};
void Other::test(){ /*do something*/}
what would be the benefit of hidding the Other class in the Base class?
class Base{
virtual void test() = 0;
};
Base obj; // #0
#0 is ill-formed as Base is an abstract class, as it has at least one pure abstract member function.
Abstract class
Defines an abstract type which cannot be instantiated, but can be
used as a base class.
A pure virtual function is a virtual function whose declarator has the
following syntax:
declarator virt-specifier(optional) = 0
[...] An abstract class is a class that either defines or inherits
at least one function for which the final overrider is pure virtual.
Dynamic dispatch on polymorphic objects happens when you are dispatching to a virtual function from a base pointer or reference, which (for the specific runtime call) references a derived object.
In the following example:
struct Base {
virtual void test() const = 0;
};
struct A final : public Base {
void test() const override {}; // #1
};
struct B final : public Base {
void test() const override {}; // #2
};
void f(Base const& b) {
b.test(); // #3
}
the call to the virtual member function test() at #3 can dispatch to either A::test() or B::test(), depending on the argument to the function f.
f(A{}); // 'test()' call in 'f' dispatches to #1
f(B{}); // 'test()' call in 'f' dispatches to #2
what would be the benefit of hidding the Other class in the Base class?
In your original example, the Base class declares a nested class (but does not define it) to itself, meaning the Other class declared in Base is not the same as the Other class that derives from it.
Declaring nested classes within a class is a separate topic entirely orthogonal to class inheritance hierarchies
A forward declaration outside of a base class that intends to forward declare a derived class that the base class thinks may derive from it would be an anti-pattern, as the whole point with abstract (interface) classes is to provide a public client API that can be used polymorphically by different derived classes. In other words, a base class should generally never (need to) know about its derived classes (save for the special case of static polymorphism via the curiously recurring template pattern).
The declaration of class Base::Other at line 2 in your first code example, has nothing to do with the declaration of class Other in line 5 of your first code example.
That is, the forward declaration of Base::Other does not match class Other.
There is benefit in having nested classes (for example, some implementations of the pimpl idiom do that), but to define the nested class, you would have to define it with:
class Base::Other {...}; // explicit specification of Base here
Related
I have to make a base class with one derived class in C++. In the end I need to evidence polymorphism between 2 methodes void Read and void Show.
After I did this, I have to create an abstract class Object from which the base class will be derived.This class will contain just pure virtual methods Read and Show.
I don't think I fully understand this. So I make an abstract class Object where I put these 2 methods with "=0" to mke them pure. But this means that I have to edit the base class also, to make it derived from class Object? Like, before:
class Base {
}
after
Class Base : public Object
Can someone make me understand?
You're on the right track. In your Base class, you can mark methods virtual that you intend to be polymorphic. You can set the functions = 0 if they are "pure virtual" and have no implementation in the base class, and are required in any concrete derived class.
class Base
{
public:
virtual void Read() = 0;
virtual void Show() = 0;
};
Then for your derived class you had the syntax backwards. Note that the override keyword indicates that you are overriding a virtual method from the base class. This keyword enforces that the function signature matches the one from a base class.
class Object : public Base
{
public:
void Read() override; // implement this
void Show() override; // implement this
};
The usage could look like the following. Note that you instantiate an Object but carry a pointer to a Base*. Due to polymorphism, the derived implementations are invoked.
int main()
{
Object obj;
Base* p = &obj;
p->Read(); // due to polymorphism will call Object::Read
p->Show(); // due to polymorphism will call Object::Show
}
I thought of using protected constructor, but it couldn't completely solve the purpose since the class inheriting from it would be able to instantiate the base class.
As for private constructor, the derived classes too would not be instantiated.
So, any suitable technique would be appreciated.
It is unclear what you are really asking for. So let me try to clear some points:
Pure virtual functions can have definitions
If your concern is that you want to provide definitions for all of the virtual functions in your base you can provide the definitions for the pure virtual functions, and they will be available for static dispatch.
Protected grants access to your base subobject, not to every instance of base
There is a common misconception that protected allows a particular derived type accessing any instance of base. That is not true. The keyword protected grants access to the base subobject within the derived type.
class base {
protected: base() {}
};
class derived : public base {
derived() : base() { // fine our subobject
base b; // error, `b` is not your subobject
}
};
The definition of an abstract class is one that has at least one pure virtual function (virtual function-signature = 0; You can't create an abstract class without them.
Can an abstract class be implemented without pure virtual functions in C++?
If you choose the point of view from Static Polymorphism, you can do that!
An abstract base class would be simply missing a default method implementation for an interface method from the deriving class.
Additionally you can use protected constructors for those CRTP base class templates, to require inheritance for instantiation.
UPDATE:
I found a nice slide show, that explains static vs dynamic polymorphism comprehensively. Each technique has it's pros and cons and certain fields of usage, additionally you can mix both techniques (wisely of course).
To elaborate a bit, I'll give a sample:
template<class Derived>
class AbstractBase
{
public:
// Equivalent for a pure virtual function
void foo()
{
// static_cast<> enforces an 'Is a' relation from Derived to AbstractBase
static_cast<Derived*>(this)->fooImpl();
}
// Equivalent for simple virtual function (overidable from Derived)
void bar()
{
static_cast<Derived*>(this)->barImpl();
}
// Default implementation for any call to bar()
void barImpl()
{
}
protected:
AbstractBase() {}
};
// Compilation will fail, since ConcreteClass1 doesn't provide
// a declaration for fooImpl()
class ConcreteClass1
: public AbstractBase<ConcreteClass1>
{
}
// Compiles fine
class ConcreteClass2
: public AbstractBase<ConcreteClass2>
{
public:
void fooImpl()
{
// Concrete implementation ...
}
}
The following sample shows that the pattern introduced above enforces an 'Is a' relationship between abstract class and inheriting class (the template parameter)
class ConcreteClass3
{
public:
void fooImpl()
{
// Concrete implementation ...
}
}
// Instantiation will fail, because
// * the constructor is protected
// * at least the static cast will fail
AbstractBase<ConcreteClass3> instance;
I read it in my book
An abstract class is a class that is designed to be specifically used as a base class. An abstract class contains at least one pure virtual function. You declare a pure virtual function by using a pure specifier (= 0) in the declaration of a virtual member function in the class declaration.
I have an abstract base class and want to implement a function in the derived class. Why do I have to declare the function in the derived class again?
class base {
public:
virtual int foo(int) const = 0;
};
class derived : public base {
public:
int foo(int) const; // Why is this required?
};
int derived::foo(int val) const { return 2*val; }
Consider that the derived-class definition might be in a header, whereas its implementation may be in a source file. The header typically gets included in multiple locations ("translation units"), each of which will be compiled independently. If you didn't declare the override, then the compiler wouldn't know about it in any of those other translation units.
The intention of making a function pure virtual in Base class is that the derived class must override it and provide its own implementation.
Note that presence of an pure virtual function in the class makes that class an Abstract class. In simple terms the class acts as an interface for creating more concrete classes.One cannot create objects of an Abstract class.
If you do not override the pure virtual function in derived class then the derived class contains the inherited Base class pure virtual function only and it itself acts as an Abstract class too.Once your derived class is abstract it cannot be instantiated.
So in order that your derived class be instantiated it needs to override and hence declare the pure virtual function.
You might think the compiler can deduce that you're going to have to provide an implementation of derived::foo(), but derived could also be an abstract class (and in fact that's what you'll get if you dont declare foo() in derived)
It is to override the abstraction of the base class.
If you do not re-declare it, then your derived class is also an abstract class. If you do then you now have a non-abstract type of the base.
Because the hierarchy could have more layers.
struct Base {
virtual void foo() const = 0;
virtual void bar() const = 0;
};
struct SuperBase: Base {
virtual void bar() const override;
};
struct Concrete: SuperBase {
virtual void foo() const override;
};
Here, SuperBase does not provide an implementation for foo, this needs be indicated somehow.
While you can't instantiate a class with pure virtual functions, you can still create a class like this:
class base {
public:
virtual int foo(int) const = 0;
};
class derived : public base {
public:
};
class very_derived : public derived {
public:
virtual int foo(int) const { return 2; }
};
The derived class is still an abstract class, it can't be instantiated since it doesn't override foo. You need to declare a non-pure virtual version of foo before you can instantiate the class, even if you don't define foo right away.
I know that when you want to declare a polymorphic function you have to declare the base class function virtual.
class Base
{
public:
virtual void f();
};
My question is are you required to declare the inheriting class function as virtual, even if it's expected that Child behaves as if it were "sealed"?
class Child : public Base
{
public:
void f();
};
No, you don't need to re-declare the function virtual.
A virtual function in a base class will automatically declare all overriding functions as virtual:
struct A
{
void foo(); //not virtual
};
struct B : A
{
virtual void foo(); //virtual
}
struct C : B
{
void foo(); //virtual
}
Declaring f() as virtual in Child helps some one reading the definition of Child. It is useful as documentation.
Once the base class override is marked as virtual all other overrides are implicitly so. While you are not required to mark the function as virtual I tend to do so for documentation purposes.
As of the last part: even if it's expected that Child behaves as if it were "sealed"?, if you want to seal the class, you can actually do it in C++11 (this was not fully implementable in C++03 generically) by creating a seal class like so:
template <typename T>
class seal {
seal() {}
friend T;
};
And then inheriting your sealed class from it (CRTP):
class Child : public Base, virtual seal<Child> {
// ...
};
The trick is that because of the use of virtual inheritance, the most derived type in the hierarchy must call the virtual base constructor (int this case seal<Child>), but that constructor is private in the templated class, and only available to Child through the friend declaration.
In C++ you would have to either create a seal type for every class that you wanted to seal, or else use a generic approach that did not provide a perfect seal (it could be tampered with)
I believe, a derived class can override only those functions which it inherited from the base class. Is my understanding correct.?
That is if base class has a public member function say, func, then the derived class can override the member function func.
But if the base class has a private member function say, foo, then the derived class cannot override the member function foo.
Am i right?
Edit
I have come up with a code sample after studying the answers given by SO members. I am mentioning the points which i studied as comments in the code. Hope i am right. Thanks
/* Points to ponder:
1. Irrespective of the access specifier, the member functions can be override in base class.
But we cannot directly access the overriden function. It has to be invoked using a public
member function of base class.
2. A base class pointer holding the derived class obj's address can access only those members which
the derived class inherited from the base class. */
#include <iostream>
using namespace std;
class base
{
private:
virtual void do_op()
{
cout << "This is do_op() in base which is pvt\n";
}
public:
void op()
{
do_op();
}
};
class derived: public base
{
public:
void do_op()
{
cout << "This is do_op() in derived class\n";
}
};
int main()
{
base *bptr;
derived d;
bptr = &d;
bptr->op(); /* Invoking the overriden do_op() of derived class through the public
function op() of base class */
//bptr->do_op(); /* Error. bptr trying to access a member function which derived class
did not inherit from base class */
return 0;
}
You can override functions regardless of access specifiers. That's also the heart of the non-virtual interface idiom. The only requirement is of course that they are virtual.
But if the base class has a private member function say, foo, then the derived class cannot override the member function foo.
In Java, you can't. In C++, you can.
You are correct in that to override a function in a derived class, it must inherit it from the base class (in addition, the base class function must be virtual). However you are wrong about your assumption that virtual functions are not inherited. For example, the following works well (and is actually a known idiom for precondition/postcondition checking):
class Base
{
public:
void operate_on(some thing);
private:
virtual void do_operate_on(some thing) = 0;
};
void Base::operate_on(some thing)
{
// check preconditions
do_operate_on(thing);
// check postconditions
}
class Derived: public Base
{
// this overrides Base::do_operate_on
void do_operate_on(some thing);
};
void Derived::do_operate_on(some thing)
{
// do something
}
int main()
{
some thing;
Base* p = new Derived;
// this calls Base::operate_on, which in turn calls the overridden
// Derived::do_operate_on, not Base::do_operate_on (which doesn't have an
// implementation anyway)
p->operate_on(thing);
delete p;
}
A way to see that private methods are really inherited is to look at the error messages generated by the following code:
class Base
{
private:
void private_method_of_B();
};
class Derived:
public Base
{
};
int main()
{
Derived d;
d.private_method_of_B();
d.method_that_does_not_exist();
}
Trying to compile this with g++ leads tot he following error messages:
privatemethodinheritance.cc: In function 'int main()':
privatemethodinheritance.cc:4: error: 'void Base::private_method_of_B()' is private
privatemethodinheritance.cc:15: error: within this context
privatemethodinheritance.cc:16: error: 'class Derived' has no member named 'method_that_does_not_exist'
If class Derived wouldn't inherit that function, the error message would be the same in both cases.
No You can not over ride any function in base class .
My reason for this notion is that if you define the function in derived class that has the same function signiture in base class , the base class function will become hidden for derived class .
For more information about this exciting issue just visit :
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Foverload_member_fn_base_derived.htm
It's also depends on the type of inheritance
class Derived : [public | protected | private] Base { };
In order to override a function inherited from base class, it should be both virtual, and classified as public or protected.