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.
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;
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
The following code is based on the example on page 298 of C++ Templates: the Complete Guide. I removed the parts not relevant to my question.
class Virtual {
public:
virtual void foo() {
}
};
class Base : private Virtual {
public:
void foo() {
std::cout << "Base::foo()" << '\n';
}
};
class Derived : public Base {
public:
void foo() {
std::cout << "Derived::foo()" << '\n';
}
};
int main()
{
Base *p = new Derived;
p->foo(); // calls Derived::foo()
}
I do not understand how the call p->foo() ends up calling Derived::foo. More concretely, the static type of p is Base*. Base::foo is non-virtual. Now, Base privately inherits from 'Virtual', which has its own foo and it looks as if Base::foo somehow gets the virtual specifier from Virtual::foo. What is actually going on here?
The virtualness of foo is inherited from the base class Virtual.
In fact, writing virtual in Derived::foo will be superfluous and many developers will omit it. You cannot undo virtualness once you've marked that function as virtual in a base class.
You can force a call of Base::foo by writing p->Base::foo(); but that's an ugly contrivance.
Say I have defined 2 classes, a base class and a derived class. Then I write a function that takes the base class as an input.
When I use that function I will only ever pass in derived class functions and want to be able to access a redefined version of a base class method.
So lets say both the base and derived class have a method foo(). I create a derived class variable and pass it into a function that only accepts base class variables. Inside that function I want to access foo() as it is defined in the derived class, not as it is defined in the base class.
I have tried protected but that doesn't work.
Make the function virtual and that will access the derived class implementation on a base class pointer if the pointer points to a derived class instance.
Make sure you are passing a pointer or a reference (NOT passing the object by value)
class BaseT
{
public: virtual void f(string msg) { cout << msg << " from Base" << endl; }
};
class DerivedT: public BaseT
{
public: void f(string msg) { cout << msg << " from Derived" << endl; }
};
// myFunc says hi from derived or from base
// depending on what b really points to
void myFunc (BaseT *b) { b->f("hi"); }
int main(int argc, char* argv[])
{
DerivedT d;
BaseT b;
myFunc (&d);
myFunc (&b);
return 0;
}
I have following
class base
{
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};
now I have
base* pbase = new derived();
pbase->myFunc();
I am getting error myFunc is not a member function of base.
How to avoid this? and how to make myFunc get called?
Note I should have base class contain no function as it is part of design and above code is part of big function
If you are adamant that this function should NOT be a part of base, you have but 2 options to do it.
Either use a pointer to derived class
derived* pDerived = new derived();
pDerived->myFunc();
Or (uglier & vehemently discouraged) static_cast the pointer up to derived class type and then call the function
NOTE: To be used with caution. Only use when you are SURE of the type of the pointer you are casting, i.e. you are sure that pbase is a derived or a type derived from derived. In this particular case its ok, but im guessing this is only an example of the actual code.
base* pbase = new derived();
static_cast<derived*>(pbase)->myFunc();
myfunc needs to be accessible from the base class, so you would have to declare a public virtual myfunc in base. You could make it pure virtual if you intend for base to be an abstract base class, i.e one that cannot be instantiated and acts as an interface:
class base
{
public:
virtual void myfunc() = 0; // pure virtual method
};
If you ant to be able to instantiate base objects then you would have to provide an implementation for myfunc:
class base
{
public:
virtual void myfunc() {}; // virtual method with empty implementation
};
There is no other clean way to do this if you want to access the function from a pointer to a base class. The safetest option is to use a dynamic_cast
base* pbase = new derived;
....
derived* pderived = dynamic_cast<derived*>(pbase);
if (derived) {
// do something
} else {
// error
}
To use the base class pointer, you must change the base class definition to be:
class base
{
public:
virtual void myFunc() { }
};
I see no other way around it. Sorry.
You could add it as a member of base and make it a virtual or pure virtual function. If using this route however, you should also add a virtual destructor in the base class to allow successful destruction of inherited objects.
class base
{
public:
virtual ~base(){};
virtual void myFunc() = 0;
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};