Inheritance of templated methods - c++

I have a question about inheritance and template methods. Suppose I have this two classes
class Base
{
public:
template<typename T>
void print(const T& s) {std::cout << "Base (templated) prints " << s << "\n";}
virtual void print(int i) {std::cout << "Base prints " << i << "\n";}
};
class Derived : public Base
{
public:
void print(int i) {std::cout << "Derived prints " << i << "\n";}
}
int main()
{
Derived d;
d.print(3); // works fine
std::string s = "hi";
d.print(s); // does not compile
return 0;
}
The compiler tells me ''no matching function for call to ‘Derived::print(std::string&)’'.
But Derived, inheriting from Base, should also allow a call to the template method print(..), no?
Things are also weird cause if I don't define a method "print" in the derived class, then everything works fine and the compiler calls the base class template method.
Things work fine also if I define the template method also in the derived class, which calls the base class one, but that does not seem right to me...
Thanks for your help.

Declaring a function in the derived class hides any functions with the same name in the base class. You can unhide them with a using declaration:
class Derived : public Base
{
public:
// Add this
using Base::print;
void print(int i) {std::cout << "Derived prints " << i << "\n";}
}

This is a standard base name hide, and has absolutely nothing whatsoever to do with the fact that the base class function is a template. It could be the second coming of Jesus and the compiler would still hide it. It's normal behaviour, implemented to try and protect derived classes from unexpected changes in base classes.

Related

How to execute a virtual function from a base class without the explicit call of Base::func() in a derived class?

I'm a newbie in C++ and have a question. I can't find any related stuff for this question on Google.
Is it possible in C++ for code in a virtual function to be called from the base class without invoking it with Base::func() in the derived class?
Here is an example of what I mean:
class Base {
public:
virtual void func(void) { cout << "Base func()" << endl; }
};
class Derived : Base {
public:
virtual void func(void) { cout << "Derived func()" << endl; }
};
The output should be the following when the function func is called from Derived:
Base func()
Derived func()
Is this even possible in C++? Or, is there another way to implement this behavior?
Is that intention even possible in C++? Or is there a other way to implement this behavior in C++?
You can get that behavior only if you add
Base::func();
in the implementation of Derived::func(). The language does not provide a mechanism to make that automatic.
You can make the base class get the calls first by making the interface non-virtual, and then call the (private) derived function from there:
class Base {
public:
void func()
{
cout << "Base func()" << endl;
derived_func();
}
private:
virtual void derived_func() { }
};
class Derived : Base {
private:
virtual void derived_func() { cout << "Derived func()" << endl; }
};
You have call the base class in derived class implementation to make that happen
class Base {
public:
virtual void func(void) { cout << "Base func()" << endl; }
};
class Derived : Base {
public:
virtual void func(void)
{
Base::function();
cout << "Derived func()" << endl;
}
};
But this is still calling Base::func() from Derived::func()
You can, however, achieve what you want if the func() was actually your constructor.

I get the error: cannot declare variable ‘a’ to be of abstract type ‘A’

Here is my code:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void Sub1() = 0;
virtual void Sub2();
virtual void Sub3();
void Sub4();
};
class A : public Base
{
public:
void Sub2();
void Sub4();
};
class B : public A
{
public:
virtual void Sub1();
void Sub2();
};
class C : public Base
{
public:
virtual void Sub1();
virtual void Sub4();
};
void Base::Sub2()
{
cout << "Hello from Base::Sub2()" << endl;
}
void Base::Sub3()
{
cout << "Hello from Base::Sub3()" << endl;
Sub1(); // DONT MISS THIS CALL IN YOUR ANSWER
}
void Base::Sub4()
{
cout << "Hello from Base::Sub4()" << endl;
}
void A::Sub2()
{
cout << "Hello from A:Sub2()" << endl;
}
void A::Sub4()
{
cout << "Hello from A:Sub4()" << endl;
}
void B::Sub1()
{
cout << "Hello from B:Sub1()" << endl;
}
void B::Sub2()
{
cout << "Hello from B:Sub2()" << endl;
}
void C::Sub1()
{
cout << "Hello from C:Sub1()" << endl;
}
void C::Sub4()
{
cout << "Hello from C:Sub4()" << endl; //error used to say from Sub2
}
void Sub(Base& x)
{
x.Sub1();
x.Sub2();
x.Sub3();
}
void AnotherSub(A& a)
{
a.Sub1();
a.Sub2();
a.Sub4();
}
int main()
{
A a; // wont compile
B b;
C c;
Sub(a);
Sub(b);
Sub(c);
AnotherSub(b);
}
I'm having trouble with the A a; and obviously the end Sub(a); because a cannot be used, but at the very end, where it says, "error: cannot declare variable ‘a’ to be of abstract type ‘A’" Any help would be appreciated, Thanks.
--- Also if it helps, the output without the A a; works and looks like:
Hello from B:Sub1()
Hello from B:Sub2()
Hello from Base::Sub3()
Hello from B:Sub1()
Hello from C:Sub1()
Hello from Base::Sub2()
Hello from Base::Sub3()
Hello from C:Sub1()
Hello from B:Sub1()
Hello from B:Sub2()
Hello from A:Sub4()
This line into your class Base:
virtual void Sub1() = 0;
Make the class Base or any class extending it an abstract class if you don't implement the function Sub1, which is the case of your class A.
You cannot create instances of abstract classes, as it has methods with no implementation, which means impossible to call. This kind of classes can only be used through inheritance.
So you need to implement it directly on Base or A if you want to create A instances.
Your compiler is right: you cannot create a variable of abstract typ. Your class Base is abstract because it declares a pure virtual method, that is a function without any implementation:
virtual void Sub1() = 0;
Your class A derived from Base is abstract, too, because it does not provide an overriding implementation for the method.
You must provide an implementation to all declared virtual methods to make a type instantiable. As you override a pure virtual Sub1() in class B, you can create variables of class B (and its descendant classes), but class A cannot be used itself as an actual type for a variable.
You are extending Base class from A but you didn't implement the pure virtual method in A. So, you need to make A as abstract class. It can't be a concrete class.
To ignore making A as abstract and to use it as a concrete class, just override the pure virtual method too and define it with no statements in it. Now you can create an instance for A.
What I want to add is Since Base is abstract and class A doesn't implement one of its pure virtual function so A is also abstract. As abstract class cant be instantiated (only pointers and references are allowed) we use pointers of abstract class (say pointer to A) to instantiate object of classes derived from abstract class (A or base in this case).
So you need to provide implementation of pure virtual function and have to use pointer to A like
A *a;
a = new B(); // it would compile now
Hope you got my point.

C++ Method overloading by Inherited Parameter Type

If I have a Base and a Derived Class:
class Base {
//...
};
class Derived : public Base {
//...
};
Is it possible to overload functions in the following way?
void DoSomething(Base b) {
cout << "Do Something to Base" << endl;
}
void DoSomething(Derived d) {
cout << "Do Something to Derived" << endl;
}
What happens if I do this:
int main() {
Derived d = Derived();
DoSomething(d);
}
Derived is also a Base.. so which version gets called?
Yes, C++ lets you overload functions for base and derived classes. In fact, this mechanism is used by the standard library <algorithm> functions to select the correct algorithm depending on the types of the iterators passed in.
A Derived object is also a Base, but DoSomething(Derived) is an exact match, so it's preferred. DoSomething(d) will call DoSomething(Derived).
However, note that you can't get polymorphic behaviour this way. That is, if you have a Base& that actually refers to a Derived object, it still calls DoSomething(Base): that is, it dispatches on the static type. (In fact, since you are passing by value, it copies out only the Base part of the object into the parameter.) To get polymorphic behaviour, you would have to make DoSomething into a virtual member function (or make DoSomething(Base& b) call a virtual member function on b.)
The derived function will be called and used because it matches this "DoSomething(Derived d)"
signature.
Have you consider using the code like this instead:
#include<iostream>
using namespace std;
class Base {
public:
virtual void DoSomething();
};
class Derived : public Base {
public:
void DoSomething() override;
};
void Base:: DoSomething() {
cout << "Do Something to Base" << endl;
}
void Derived :: DoSomething() {
cout << "Do Something to Derived" << endl;
}
int main() {
Base *d = new Derived();
d->DoSomething();
delete d;
return 0;
}
It accomplished the same task, and allows you to take advantage of polymorphisms strength.

Access overloaded base class method with same name as derived method

I'm attempting to call a method from a base class with the same name as a method in the derived class. Here's a simplified example:
#include <iostream>
using namespace std;
class Base
{
public:
void print() {
cout << "Printing from base" << endl;
}
void print(int num) {
cout << "Printing number from base: " << num << endl;
}
};
class Derived : public Base
{
using Base::print;
public:
void print() {
cout << "Printing from derived" << endl;
}
};
int main()
{
Derived x;
x.print();
x.Base::print(1);
//x.print(1); // Gives a compilation error
return 0;
}
Basically, I'd like to be able to call x.print(1) and get "Printing number from base: 1", that is, automatically call the method which matches the signature, even though it resides in the base class.
Without the using Base::print;, I get error: no matching function for call to 'Derived::print(int)', which makes perfect sense due to name hiding.
Thus, I added that line, but now the error is error: 'void Base::print(int)' is inaccessible
Why is this the case? I use public inheritance, so I would have thought it was readily available?
As demonstrated in the example, it works fine to manually call x.Base::print(1);, but I would like to do it more transparently. Then of course I can re-implement a wrapper to the function in the derived class, but that does not seem very elegant either.
I apologize if this has been covered in an earlier question, I read a bunch of them and found a lot of similar cases, but nothing that helped me.
The placement of the using directive decides about the visibility. Simply place it into the public area and you should be fine:
//...
class Derived : public Base
{
public:
using Base::print;
void print() {
cout << "Printing from base" << endl;
}
};
//...
http://ideone.com/06NNk
You can make your functions virtual. Any virtual functions inherited from the base class that aren't overloaded will be called through the derived class.
class base
{
public:
virtual void Foo() {}
}
class Derived
{
}
Derived d;
d.foo(); // calls base::foo()

C++ Virtual Functions Question

Hey, so if I have a Base class and 2 derived classes...
class Base
{
virtual void Output()
{
cout << "OUTPUTTING A BASE OBJECT" << endl;
}
};
class Derived : public Base
{
void Ouput()
{
cout << "OUTPUTTING A DERIVED" << endl;
}
};
class OtherDerived : public Base
{
};
As I understand it, if I try to call Output from OtherDerived, it would fail. Is there a way to override Output for some derived versions of Base but not others?
Calling Output for objects of the OtherDerived class fails not because it's virtual, but because it's declared private in Base (well not explicitly - but private is the default in classes when nothing else is specified)
Change the declaration of Base to:
class Base
{
public:
virtual void Output()
{
cout << "OUTPUTTING A BASE OBJECT" << endl;
}
};
And this will work. protected will also work. Since Output isn't pure virtual, it can be called from subclasses that don't override it.
It would not fail - it would call Base::Output. What you want, ie. overriding "for some derived classes, but not others" is how inheritance works. You don't need to do anything further.