I was trying to understand the implementation code of "final" in cpp:
following is the code:
/* A program with compilation error to demonstrate that Final class cannot
be inherited */
class Final; // The class to be made final
class MakeFinal // used to make the Final class final
{
private:
MakeFinal() { cout << "MakFinal constructor" << endl; }
friend class Final;
};
class Final : virtual MakeFinal
{
public:
Final() { cout << "Final constructor" << endl; }
};
class Derived : public Final // Compiler error
{
public:
Derived() { cout << "Derived constructor" << endl; }
};
int main(int argc, char *argv[])
{
Derived d;
return 0;
}
Output: Compiler Error
In constructor 'Derived::Derived()':
error: 'MakeFinal::MakeFinal()' is private
In this I could not understand the logic of virtually inheriting the MakeFinal class.
We could simply have inherited it(makeFinal class) as public and even in that case we would have not been able to inherit it further(because the constructor of Makefile is private and only Final class being its friend could have the access of it).
Any pointer??
It wouldn't work. Non-virtual base classes are always initialised by the class which is immediately derived from them. That is, if the scenario were as follows:
class Final : public MakeFinal
{
public:
Final() {}
};
class Derived : public Final
{};
then the ctor of Derived only initialises Final, which is fine (Final has a public ctor). Final's ctor then initialises MakeFinal, which is also possible, since Final is a friend.
However, for virtual base classes, the rule is different. All virtual base classes are initialised by the ctor of the most-derived object. That is, when creating an instance of Final, it's Final's ctor which initialises MakeFinal. However, when trying to create an instance of Derived, it must be Derived's ctor which initialises MakeFinal. And that is impossible, due to MakeFinal's private ctor.
Also note that C++11 introduced the keyword final for classes (and virtual functions).
Related
What is the derived class doing in this code like:
class Base
{
public:
virtual std::string Name(){ return "Base Class"}
};
class Derived : public Base
{
public:
std::string Name() {return "Derived Class"}
}
int main()
{
Base* object = new Derived();
return 0;
}
I was following a tutorial but didn't understand What does Derived class in The instantiation of Base Class was doing in the above code.
The goal is to implement polymorphism, it's a OOP concept which allows you, among other things, to make derived class methods override the base class.
Consider the following:
class Base {
public:
//virtual keyword allows method to be overriden
virtual std::string Name() { return "Base Class"; }
//virtual destructor needed for polymorphism otherwise it can lead to undefined behavior
virtual ~Base(){}
};
class Derived : public Base {
public:
//optional keyword override signal the method has been overriden
std::string Name() override { return "Derived Class"; }
};
class Derived2 : public Base {
public:
std::string Name() override { return "Derived Class 2"; }
};
int main() {
Base *object = new Derived();
Base *object2 = new Derived2();
Base *object3 = new Base();
//collection of objects of type Base* which can hold any class of the family
Base *collection[] = {object, object2, object3};
for (auto &obj : collection) {//test print
std::cout << obj->Name() << std::endl;
}
}
As the comments explain, I can have a collection of different objects of the same family and when you call Name() the method call will deppend on the object.
Output:
Derived Class
Derived Class 2
Base Class
modifying main to be :
int main()
{
Base* object = new Derived();
std::cout << object->Name() << std::endl;
return 0;
}
and adding 3 missing ';' in your code, you will see that writes Derived Class, the called method Name is the one of the real type of object being Derived.
Note while Name is virtual in Base it is also in Derived even you do not said explicitly.
virtual allows to use the real type of an object when you apply an method on, so even object is declared Base when Name is virtual the called version is the one of the real type being Derived
But if you remove virtual in the definition of Name in Base that writes Base Class because object being declared Base the called method is Name defined on Base.
The result will be the same adding virtual on Derived but still removing it on Base, because for the compiler object being declared Base and Name being not virtual on Base that one is called without considering the real type of object
So, having :
#include <iostream>
#include <string>
class Base
{
public:
virtual std::string virtualName(){ return "Base Class";}
std::string nonVirtualName(){ return "Base Class";}
};
class Derived : public Base
{
public:
std::string virtualName() {return "Derived Class";} // implicitely virtual
std::string nonVirtualName(){ return "Base Class";}
};
int main()
{
Base* object = new Derived();
std::cout << object->virtualName() << std::endl;
std::cout << object->nonVirtualName() << std::endl;
return 0;
}
Compilation and execution :
bruno#bruno-XPS-8300:/tmp$ g++ -Wall a.cc
bruno#bruno-XPS-8300:/tmp$ ./a.out
Derived Class
Base Class
bruno#bruno-XPS-8300:/tmp$
Note if you add delete object; at the end of main and because of the default destructor in not virtual the called destructor is the one of Base exactly for nonVirtualName and nothing is done for Derived. Defining the destructor virtual on Base is the right way to do, that implies the destructor is at least implicitly virtual on Derived allowing to have both destructors executed on delete object;
Im reading this article on constructors for c++
We recommend that you be careful when you call virtual functions in
constructors. Because the base class constructor is always invoked
before the derived class constructor, the function that's called in
the base constructor is the base class version, not the derived class
version. In the following example, constructing a DerivedClass causes
the BaseClass implementation of print_it() to execute before the
DerivedClass constructor causes the DerivedClass implementation of
print_it() to execute:
the example:
class BaseClass {
public:
BaseClass() {
print_it();
}
virtual void print_it() {
cout << "BaseClass print_it" << endl;
}
};
class DerivedClass : public BaseClass {
public:
DerivedClass() {
print_it();
}
virtual void print_it() {
cout << "Derived Class print_it" << endl;
}
};
int main() {
DerivedClass dc;
}
Here's the output:
BaseClass print_it
Derived Class print_it
I tried this code and the output is as stated above.
However I also tried the same example without the virtual keyword:
class BaseClass {
public:
BaseClass() {
print_it();
}
void print_it() {
cout << "BaseClass print_it" << endl;
}
};
class DerivedClass : public BaseClass {
public:
DerivedClass() {
print_it();
}
void print_it() {
cout << "Derived Class print_it" << endl;
}
};
int main() {
DerivedClass dc;
}
and got the same result.
So what is the difference and what is the danger they are warning for?
#marked as duplicate:
This question is different as the consturctors both call the virtual method instead of one constructor calling the virtual method.
There is no difference. That's the danger.
If you did not know better then you might expect this instead:
Derived Class print_it
Derived Class print_it
The expectation is there because if you call the virtual print_it() from functions in Base, polymorphism means you'll usually get the Derived version instead.
But, when you write it in the Base constructor, the Base part of the object is still under construction, and the "dynamic type" of the object under construction is still Base, not Derived. So you do not get the usual polymorphic behaviour.
The article is warning you about this fact.
Basically, my question is related to name lookup and using declaration (http://en.cppreference.com/w/cpp/language/namespace).
Suppose we have the following (definitely stupid) codes:
class Base {
public:
void fun()
{std::cout << "Base fun" << std::endl;}
};
class Derived : public Base {
public:
// Here both names "fun" are visible or not?
using Base::fun;//let's call this func_1
void fun() //let's call this func_2
{
std::cout << "Derived fun" << std::endl;
}
};
Derived d;
d.fun(); // This resolves to func_2, why?
Therefore, my understand is now we should have both names visible, and then for name lookup, there should be some ambiguity. But actually it is not. What is the reason or in other words, do I misunderstand some concepts?
The standard has a special rule for this case.
When a using-declaration brings names from a base class into a derived class scope, member functions and
member function templates in the derived class override and/or hide member functions and member function
templates with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (if any) in a
base class (rather than conflicting).
([namespace.udecl]/15)
Note that as usual, you can force Base::fun to be called by doing d.Base::fun().
The link you're referencing is for namespace's, you should instead refer to the class using-declaration where it states:
If the derived class already has a member with the same name, parameter list, and qualifications, the derived class member hides or overrides (doesn't conflict with) the member that is introduced from the base class.
In the case of your posted code, void fun() in Base is hidden by void fun() in Derived, so no, they're not both "visible", unless you are explicit when you call fun, example:
class Base {
public:
void fun() { std::cout << "base" << std::endl; }
};
class Derived : public Base {
public:
using Base::fun;
void fun() { std::cout << "derived" << std::endl; }
};
Derived d;
d.fun(); // name lookup calls Derived::fun
d.Base::fun(); // explicitly call Base::fun
Additionally, since you've publicly derived from Base, strictly speaking, you don't need the using declaration; you would in the instance that void fun() were protected in Base or you private/protected'ly inherited from Base, example:
#include <iostream>
class Base {
public:
void fun() { std::cout << "base" << std::endl; }
protected:
void fun2() { std::cout << "base2" << std::endl; }
};
// class default is private
class Private : Base {
public:
// fun() won't be accessible since private inheritance and no using
// fun2 can now be accessed directly
using Base::fun2;
};
class Public : public Base {
public:
// fun is already public
using Base::fun2; // bring into scope
};
class Derived : public Base {
public:
using Base::fun;
using Base::fun2;
// overriden method fun, no conflict, choose this method if type is Derived
void fun() { std::cout << "derived" << std::endl; }
};
int main(int argc, char* argv[])
{
Private p;
Public u;
Derived d;
// generates a compiler error since Base is privately inherited
//p.fun();
p.fun2(); // OK, output: base2
u.fun(); // OK, output: base
u.fun2(); // OK, output: base2
// use Derived::fun since override
d.fun(); // OK, output: derived
d.Base::fun(); // OK, output: base
d.fun2(); // OK, output: base2
return 0;
}
Hope that can help
1.In the main function below, why does d.foo(9.5) not select the Base::foo(double) method from the base class? Doesn't the derived class inherit that method?
2.What causes the compile error?
class Base {
public:
virtual void foo(int){
cout << "Base::foo(int)" << endl;
}
virtual void foo(double){
cout << "Base::foo(double)" << endl;
}
};
class Derived : public Base {
public:
virtual void foo(int){
cout << "Derived::foo(int)" << endl;
}
};
void main() {
Derived d;
Base b, *pb = &d;
d.foo(9); // selects Derived::foo(int)
d.foo(9.5); // selects Derived::foo(int)
pb->foo(9); // selects Derived::foo(int)
pb->foo(9.5); // selects Base::foo(double)
Derived * d;
d->foo(9); // compile error
}
The compilation error is because of two variables with the same name in main().
As to your problem with inherited functions not being called for an instance of your Derived (except via pointer to Base)
The standard describes the "hiding rule", which makes this happen. Essentially, member functions declared in derived classes hide inherited functions with the same name but different signature inherited from the base class. The hiding rule is independent of whether the inherited functions are virtual or not.
The common solution is to introduce all inherited functions from the base class with using Base::foo. For example,
class Base {
public:
virtual void foo(int){
cout << "Base::foo(int)" << endl;
}
virtual void foo(double){
cout << "Base::foo(double)" << endl;
}
};
class Derived : public Base {
public:
using Base::foo;
virtual void foo(int){
cout << "Derived::foo(int)" << endl;
}
};
Another solution is to remember to explicitly override all inherited versions of the function (implement the derived class version to simply call the base class version of each function). This works with older compilers that do not support a using directive like the above. The catch is that it is necessary to explicitly do this with every inherited overload, and it is easy to miss one.
In the main function below, why does d.foo(9.5) not select the Base::foo(double) method from the base class? Doesn't the derived class inherit that method?
Yes, but it's hidden by the function with the same name in the derived class. You can unhide it with a using-declaration in the derived class:
using Base::foo;
What causes the compile error?
You're trying to declare a second variable called d. Change the name to something that's not already used; and initialise it to point to a valid object, otherwise you'll have a runtime error or other undefined behaviour.
Derived * pd = &d;
pd->foo(9); // selects Derived::foo(int)
Also, main has the wrong return type. It must return int.
1) Because this is exactly how polymorphism work. If a virtual function is redefined in a derived class, this (and only this) redefined version will be called. If the function is not virtual it's vice versa: only the base class function will be called.
//Example 1: non-virtual function
class Base
{
public:
void foo()
{
std::cout << "Base";
}
}
class Derived : public Base
{
public:
void foo()
{
std::cout << "Derived";
}
}
Base * base = new Base();
base->foo()//prints "Base"
Base * derived = new Derived();
derived->foo()//prints "Base", since the function is not virtual, and the version from the base class is called
//Example 2: virtual function
class Base
{
public:
virtual void foo()
{
std::cout << "Base";
}
}
class Derived : public Base
{
public:
void foo()
{
std::cout << "Derived";
}
}
Base * base = new Base();
base->foo()//prints "Base"
Base * derived = new Derived();
derived->foo()//prints "Derived", since the function is virtual, and the redefined version from Derived class is called
2) The compile error happens because you have a conflicting declaration - two objects are called d.
Derived * d;
d->foo(9); // compile error
You don't have instantiated the object:
Derived * d = new Derived;
If you not create the object the compiler use the previous declaration of d: Derived d that is not a pointer.
#include <iostream>
using namespace std;
class base{
public:
int i;
base(){
i=1;
cout<<"Base Constructor";
}
};
class derived: private base{
public:
derived(){
i=2;
cout<<"Derived constructor";
}
};
int main(){
derived c;
return 0;
}
For the above code why am I getting the output as
"Base ConstructorDerived Constructor"
even though I inherited using private?
Why am I still be able to access it from main function?
You aren't.
Your main function accesses derived's constructor, which it has access to.
And derived's constructor accesses base's constructor, which it has access to.
A constructor automatically initializes the base classes and the members before executing the body of the constructor. Private inheritance doesn't change that. It just makes the base part of the class not accessible outside the class. Since it is the derived class constructor that is calling the base class constructor, the private inheritance doesn't restrict what it can do.
What you mean to do is make the constructor of the base class protected. Then only derived classes can use it:
class base
{
protected:
base() : i(1) { }
private:
int i;
};
class derived : private base
{
public:
derived() : base() { }
};
int main()
{
// base b; // error: inaccessible constructor base::base()
derived d; // fine
}
A somewhat popular pattern is also to make the destructor protected. You get the point, though.